This is an automated email from the ASF dual-hosted git repository.

tsato pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git


The following commit(s) were added to refs/heads/main by this push:
     new 1cc067e  feat(cli): initial support for describing Kamelets with kamel 
describe #2312
1cc067e is described below

commit 1cc067e9a8e41ecb9eecc99d3123a3547f9bf6ee
Author: Tadayoshi Sato <sato.tadayo...@gmail.com>
AuthorDate: Wed Jun 2 14:25:01 2021 +0900

    feat(cli): initial support for describing Kamelets with kamel describe #2312
---
 pkg/apis/camel/v1alpha1/jsonschema_types.go      |  14 +-
 pkg/apis/camel/v1alpha1/kamelet_types_support.go |  65 +++++++++
 pkg/cmd/describe.go                              |   1 +
 pkg/cmd/describe_kamelet.go                      | 172 +++++++++++++++++++++++
 4 files changed, 251 insertions(+), 1 deletion(-)

diff --git a/pkg/apis/camel/v1alpha1/jsonschema_types.go 
b/pkg/apis/camel/v1alpha1/jsonschema_types.go
index db3b10a..038307b 100644
--- a/pkg/apis/camel/v1alpha1/jsonschema_types.go
+++ b/pkg/apis/camel/v1alpha1/jsonschema_types.go
@@ -123,6 +123,18 @@ func (m *RawMessage) UnmarshalJSON(data []byte) error {
        return nil
 }
 
+// String returns a string representation of RawMessage
+func (m *RawMessage) String() string {
+       if m == nil {
+               return ""
+       }
+       b, err := m.MarshalJSON()
+       if err != nil {
+               return ""
+       }
+       return string(b)
+}
+
 var _ json.Marshaler = (*RawMessage)(nil)
 var _ json.Unmarshaler = (*RawMessage)(nil)
 
@@ -133,4 +145,4 @@ type JSONSchemaURL string
 type ExternalDocumentation struct {
        Description string `json:"description,omitempty""`
        URL         string `json:"url,omitempty"`
-}
\ No newline at end of file
+}
diff --git a/pkg/apis/camel/v1alpha1/kamelet_types_support.go 
b/pkg/apis/camel/v1alpha1/kamelet_types_support.go
index 9e6f540..52635f2 100644
--- a/pkg/apis/camel/v1alpha1/kamelet_types_support.go
+++ b/pkg/apis/camel/v1alpha1/kamelet_types_support.go
@@ -18,6 +18,8 @@ limitations under the License.
 package v1alpha1
 
 import (
+       "sort"
+
        v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
        corev1 "k8s.io/api/core/v1"
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -137,6 +139,45 @@ func (in *KameletStatus) RemoveCondition(condType 
KameletConditionType) {
        in.Conditions = newConditions
 }
 
+// SortedDefinitionPropertiesKeys returns the sorted keys of the Kamelet 
definition properties
+func (k *Kamelet) SortedDefinitionPropertiesKeys() []string {
+       if k.Spec.Definition == nil {
+               return []string{}
+       }
+       props := k.Spec.Definition.Properties
+       if len(props) == 0 {
+               return []string{}
+       }
+       res := make([]string, len(props))
+       i := 0
+       for key := range props {
+               res[i] = string(key)
+               i++
+       }
+       sort.Strings(res)
+       return res
+}
+
+// SortedTypesKeys returns the sorted keys of the Kamelet spec types
+func (k *Kamelet) SortedTypesKeys() []EventSlot {
+       types := k.Spec.Types
+       if len(types) == 0 {
+               return []EventSlot{}
+       }
+       strs := make([]string, len(types))
+       i := 0
+       for key := range types {
+               strs[i] = string(key)
+               i++
+       }
+       sort.Strings(strs)
+       res := make([]EventSlot, len(types))
+       for i, s := range strs {
+               res[i] = EventSlot(s)
+       }
+       return res
+}
+
 func ValidKameletName(name string) bool {
        return !reservedKameletNames[name]
 }
@@ -150,3 +191,27 @@ func ValidKameletProperties(kamelet *Kamelet) bool {
        }
        return true
 }
+
+// NewKamelet creates a new kamelet
+func NewKamelet(namespace string, name string) Kamelet {
+       return Kamelet{
+               TypeMeta: metav1.TypeMeta{
+                       APIVersion: SchemeGroupVersion.String(),
+                       Kind:       KameletKind,
+               },
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: namespace,
+                       Name:      name,
+               },
+       }
+}
+
+// NewKameletList creates a new list of kamelets
+func NewKameletList() KameletList {
+       return KameletList{
+               TypeMeta: metav1.TypeMeta{
+                       APIVersion: SchemeGroupVersion.String(),
+                       Kind:       KameletKind,
+               },
+       }
+}
diff --git a/pkg/cmd/describe.go b/pkg/cmd/describe.go
index 66b38f2..96a5ae7 100644
--- a/pkg/cmd/describe.go
+++ b/pkg/cmd/describe.go
@@ -85,6 +85,7 @@ func newCmdDescribe(rootCmdOptions *RootCmdOptions) 
*cobra.Command {
        cmd.AddCommand(cmdOnly(newDescribeKitCmd(rootCmdOptions)))
        cmd.AddCommand(cmdOnly(newDescribeIntegrationCmd(rootCmdOptions)))
        cmd.AddCommand(cmdOnly(newDescribePlatformCmd(rootCmdOptions)))
+       cmd.AddCommand(cmdOnly(newDescribeKameletCmd(rootCmdOptions)))
 
        return &cmd
 }
diff --git a/pkg/cmd/describe_kamelet.go b/pkg/cmd/describe_kamelet.go
new file mode 100644
index 0000000..7b1c8ff
--- /dev/null
+++ b/pkg/cmd/describe_kamelet.go
@@ -0,0 +1,172 @@
+/*
+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"
+       "io"
+       "strings"
+
+       "github.com/spf13/cobra"
+
+       k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
+
+       "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+       "github.com/apache/camel-k/pkg/util/indentedwriter"
+)
+
+func newDescribeKameletCmd(rootCmdOptions *RootCmdOptions) (*cobra.Command, 
*describeKameletCommandOptions) {
+       options := describeKameletCommandOptions{
+               rootCmdOptions,
+       }
+
+       cmd := cobra.Command{
+               Use:     "kamelet",
+               Aliases: []string{"kl"},
+               Short:   "Describe a Kamelet",
+               Long:    `Describe a Kamelet.`,
+               PreRunE: decode(&options),
+               RunE: func(_ *cobra.Command, args []string) error {
+                       if err := options.validate(args); err != nil {
+                               return err
+                       }
+                       if err := options.run(args); err != nil {
+                               fmt.Println(err.Error())
+                       }
+
+                       return nil
+               },
+       }
+
+       return &cmd, &options
+}
+
+type describeKameletCommandOptions struct {
+       *RootCmdOptions
+}
+
+func (command *describeKameletCommandOptions) validate(args []string) error {
+       if len(args) != 1 {
+               return errors.New("describe expects a Kamelet name argument")
+       }
+       return nil
+}
+
+func (command *describeKameletCommandOptions) run(args []string) error {
+       c, err := command.GetCmdClient()
+       if err != nil {
+               return err
+       }
+
+       kamelet := v1alpha1.NewKamelet(command.Namespace, args[0])
+       kameletKey := k8sclient.ObjectKey{
+               Namespace: command.Namespace,
+               Name:      args[0],
+       }
+
+       if err := c.Get(command.Context, kameletKey, &kamelet); err == nil {
+               fmt.Print(command.describeKamelet(kamelet))
+       } else {
+               fmt.Printf("Kamelet '%s' does not exist.\n", args[0])
+       }
+
+       return nil
+}
+
+func (command *describeKameletCommandOptions) describeKamelet(kamelet 
v1alpha1.Kamelet) (string, error) {
+       return indentedwriter.IndentedString(func(out io.Writer) error {
+               w := indentedwriter.NewWriter(out)
+
+               describeObjectMeta(w, kamelet.ObjectMeta)
+
+               w.Write(0, "Phase:\t%s\n", kamelet.Status.Phase)
+
+               // Definition
+               def := kamelet.Spec.Definition
+               if def != nil {
+                       w.Write(0, "Definition:\n")
+                       w.Write(1, "Title:\t%s\n", def.Title)
+                       w.Write(1, "Description:\n")
+                       for _, s := range strings.Split(def.Description, "\n") {
+                               w.Write(2, "%s\n", s)
+                       }
+                       if len(def.Required) > 0 {
+                               w.Write(1, "Required:\n")
+                               for _, req := range def.Required {
+                                       w.Write(2, "%s\n", req)
+                               }
+                       }
+                       if len(def.Properties) > 0 {
+                               w.Write(1, "Properties:\n")
+                               for _, k := range 
kamelet.SortedDefinitionPropertiesKeys() {
+                                       p := def.Properties[k]
+                                       w.Write(2, "%s:\n", k)
+                                       w.Write(3, "Title:\t%s\n", p.Title)
+                                       w.Write(3, "Description:\t%s\n", 
p.Description)
+                                       w.Write(3, "Type:\t%s\n", p.Type)
+                                       if p.Default != nil {
+                                               w.Write(3, "Default:\t%s\n", 
p.Default)
+                                       }
+                               }
+                       }
+               }
+
+               // Types
+               if len(kamelet.Spec.Types) > 0 {
+                       w.Write(0, "Types:\n")
+                       for _, k := range kamelet.SortedTypesKeys() {
+                               t := kamelet.Spec.Types[k]
+                               w.Write(1, "%s:\n", k)
+                               w.Write(2, "Media Type: %s\n", t.MediaType)
+                       }
+               }
+
+               // Flow
+               // TODO pretty print flow data
+               flow := kamelet.Spec.Flow
+               if flow != nil {
+                       w.Write(0, "Flow:\n")
+                       w.Write(1, "%s\n", string(flow.RawMessage))
+               }
+
+               // Dependencies
+               if len(kamelet.Spec.Dependencies) > 0 {
+                       w.Write(0, "Dependencies:\t\n")
+                       for _, d := range kamelet.Spec.Dependencies {
+                               w.Write(1, "%s\n", d)
+                       }
+               }
+
+               // Sources
+               if len(kamelet.Spec.Sources) > 0 {
+                       w.Write(0, "Sources:\t\n")
+                       w.Write(1, "Name\tLanguage\tCompression\tRef\tRef 
Key\n")
+                       for _, s := range kamelet.Spec.Sources {
+                               w.Write(1, "%s\t%s\t%t\t%s\t%s\n",
+                                       s.Name,
+                                       s.InferLanguage(),
+                                       s.Compression,
+                                       s.ContentRef,
+                                       s.ContentKey)
+                       }
+               }
+
+               return nil
+       })
+}

Reply via email to