Skip to content

Commit

Permalink
Merge pull request #138 from clarku/main
Browse files Browse the repository at this point in the history
Adds support for custom-columns on omc get, close #94
  • Loading branch information
gmeghnag authored Feb 15, 2024
2 parents 472afe1 + 27ce75d commit bcdf4bf
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 14 deletions.
36 changes: 22 additions & 14 deletions cmd/get/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ var yamlData []byte

var GetCmd = &cobra.Command{
Use: "get",
Short: "Get kubernetes/openshift object in tabular format or wide|yaml|json|jsonpath.",
Short: "Get kubernetes/openshift object in tabular format or wide|yaml|json|jsonpath|custom-columns.",
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
cmd.Help()
Expand Down Expand Up @@ -117,7 +117,7 @@ func init() {
GetCmd.PersistentFlags().BoolVar(&vars.NoHeaders, "no-headers", false, "When using the default or custom-column output format, don't print headers (default print headers).")
GetCmd.PersistentFlags().BoolVar(&vars.ShowManagedFields, "show-managed-fields", false, "If true, show the managedFields when printing objects in JSON or YAML format.")
GetCmd.PersistentFlags().BoolVarP(&vars.ShowLabelsBoolVar, "show-labels", "", false, "When printing, show all labels as the last column (default hide labels column)")
GetCmd.PersistentFlags().StringVarP(&vars.OutputStringVar, "output", "o", "", "Output format. One of: json|yaml|wide|jsonpath=...")
GetCmd.PersistentFlags().StringVarP(&vars.OutputStringVar, "output", "o", "", "Output format. One of: json|yaml|wide|jsonpath|custom-columns=...")
GetCmd.PersistentFlags().StringVarP(&vars.LabelSelectorStringVar, "selector", "l", "", "selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
}

Expand Down Expand Up @@ -392,23 +392,31 @@ func handleObject(obj unstructured.Unstructured) error {
}
klog.V(3).Info("INFO deserializing ", obj.GetKind(), " ", obj.GetName())
var objectTable *metav1.Table
_, ok := vars.KnownResources[strings.ToLower(obj.GetKind())]
if ok {
runtimeObjectType := deserializer.RawObjectToRuntimeObject(rawObject, vars.Schema)
if err := yaml.Unmarshal(rawObject, runtimeObjectType); err != nil {
klog.V(3).Info(err, err.Error())
}
objectTable, err = tablegenerator.InternalResourceTable(runtimeObjectType, &obj)
if strings.HasPrefix(vars.OutputStringVar, "custom-columns=") {
objectTable, err = tablegenerator.CustomColumnsTable(&obj)
if err != nil {
klog.V(3).Info("INFO ", fmt.Sprintf("%s: %s, %s", err.Error(), obj.GetKind(), obj.GetAPIVersion()))
klog.V(1).ErrorS(err, err.Error())
return err
}
} else {
objectTable, err = tablegenerator.GenerateCustomResourceTable(obj)
if err != nil {
klog.V(1).ErrorS(err, err.Error())
return err
_, ok := vars.KnownResources[strings.ToLower(obj.GetKind())]
if ok {
runtimeObjectType := deserializer.RawObjectToRuntimeObject(rawObject, vars.Schema)
if err := yaml.Unmarshal(rawObject, runtimeObjectType); err != nil {
klog.V(3).Info(err, err.Error())
}
objectTable, err = tablegenerator.InternalResourceTable(runtimeObjectType, &obj)
if err != nil {
klog.V(3).Info("INFO ", fmt.Sprintf("%s: %s, %s", err.Error(), obj.GetKind(), obj.GetAPIVersion()))
klog.V(1).ErrorS(err, err.Error())
return err
}
} else {
objectTable, err = tablegenerator.GenerateCustomResourceTable(obj)
if err != nil {
klog.V(1).ErrorS(err, err.Error())
return err
}
}
}

Expand Down
1 change: 1 addition & 0 deletions docs/subcmds/get.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ omc get pod my-pod -o yaml # Get a pod's YAML
| `-o=name` | Print only the resource name and nothing else |
| `-o=wide` | Output in the plain-text format with any additional information, and for pods, the node name is included |
| `-o=yaml` | Output a YAML formatted API object |
| `-o=custom-columns` | Allows a user to customise the fields that are output and their corresponding header names |
30 changes: 30 additions & 0 deletions pkg/tablegenerator/tablegenerator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package tablegenerator

import (
"fmt"
"regexp"
"sort"
"strings"

Expand All @@ -18,6 +19,35 @@ import (
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
)

func CustomColumnsTable(unstruct *unstructured.Unstructured) (*metav1.Table, error) {
// Matches .metadata.name and metadata.name formats
format := regexp.MustCompile(`^\.?([^{}]+)$`)
fieldSelectors := map[string]string{}
prefix := "custom-columns="
table := &metav1.Table{}
args := vars.OutputStringVar[len(prefix):]
fields := strings.Split(args, ",")

for _, field := range fields {
fieldPair := strings.Split(field, ":")
if len(fieldPair) != 2 {
return nil, fmt.Errorf("error processing column '%s': expected format <name>:<selector>", field)
}
name, selector := fieldPair[0], fieldPair[1]
name = strings.Title(strings.ToLower(name))
column := metav1.TableColumnDefinition{Name: name, Type: "string"}
table.ColumnDefinitions = append(table.ColumnDefinitions, column)
fieldSelectors[name] = selector
}
cells := make([]interface{}, 0)
for _, column := range table.ColumnDefinitions {
matches := format.FindStringSubmatch(fieldSelectors[column.Name])
cells = append(cells, helpers.GetFromJsonPath(unstruct.Object, fmt.Sprintf("%s%s%s", "{.", matches[1], "}")))
}
table.Rows = []metav1.TableRow{{Cells: cells}}
return table, nil
}

func InternalResourceTable(runtimeObject runtime.Object, unstruct *unstructured.Unstructured) (*metav1.Table, error) {
resourceKind := strings.ToLower(unstruct.GetKind())
table, err := vars.TableGenerator.GenerateTable(runtimeObject, printers.GenerateOptions{Wide: vars.Wide, NoHeaders: false})
Expand Down

0 comments on commit bcdf4bf

Please sign in to comment.