Skip to content

Commit

Permalink
escape identifiers, support si units, support lists
Browse files Browse the repository at this point in the history
  • Loading branch information
yaacov committed Feb 18, 2020
1 parent be80574 commit 1136625
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 11 deletions.
6 changes: 6 additions & 0 deletions cmd/kubesql/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ func main() {
Value: "table",
Usage: "Output format, options: table, yaml or json.",
},
&cli.BoolFlag{
Name: "si-units",
Aliases: []string{"s"},
Value: false,
Usage: "Parse values with SI units as numbers, (e.g. '1Ki' will be 1024).",
},
&cli.BoolFlag{
Name: "all-namespaces",
Aliases: []string{"A"},
Expand Down
121 changes: 111 additions & 10 deletions cmd/kubesql/print.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import (
"encoding/json"
"fmt"
"log"
"math"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -62,11 +64,35 @@ func evalFactory(c *cli.Context, item unstructured.Unstructured) semantics.EvalF
}

if len(key) > 7 && key[:7] == "labels." {
return item.GetLabels()[key[7:]], len(item.GetLabels()[key]) > 0
value, ok := item.GetLabels()[key[7:]]

// Empty label represent the label is present
if ok && len(value) == 0 {
value = "true"
}

// Missing value
if !ok {
return nil, true
}

return value, ok
}

if len(key) > 12 && key[:12] == "annotations." {
return item.GetAnnotations()[key[12:]], len(item.GetLabels()[key]) > 0
value, ok := item.GetLabels()[key[12:]]

// Empty annotations represent the annotations is present
if ok && len(value) == 0 {
value = "true"
}

// Missing value
if !ok {
return nil, true
}

return value, ok
}

if key == "created" {
Expand All @@ -80,16 +106,87 @@ func evalFactory(c *cli.Context, item unstructured.Unstructured) semantics.EvalF
// Split the key to work with the `unstructured.Nested` functions.
keys := strings.Split(key, ".")

if value, ok, err := unstructured.NestedInt64(item.Object, keys...); ok && err == nil {
return value, true
}
var object interface{}
var objectList []interface{}
var objectMap map[string]interface{}
ok := true
object = item.Object

for _, key := range keys {
if i, err := strconv.ParseUint(key, 10, 64); err == nil && i > 0 {
objectList, ok = object.([]interface{})
if !ok {
break
}

ok = i < uint64(len(objectList))
if !ok {
break
}

if value, ok, err := unstructured.NestedFloat64(item.Object, keys...); ok && err == nil {
return value, true
object = objectList[i]
} else {
objectMap, ok = object.(map[string]interface{})
if !ok {
break
}

object, ok = objectMap[key]
if !ok {
break
}
}
}

if value, ok, err := unstructured.NestedString(item.Object, keys...); ok && err == nil {
return value, true
if ok {
switch object.(type) {
case float64:
return object.(float64), true
case int64:
return float64(object.(int64)), true
case string:
if c.Bool("si-units") {
multiplier := 0.0
s := object.(string)

// Remove SI `i` if exist
// Note: we support "K", "M", "G" and "Ki", "Mi", "Gi" postfix
if len(s) > 1 && s[len(s)-1:] == "i" {
s = s[:len(s)-1]
}

// Check for SI postfix
if len(s) > 1 {
postfix := s[len(s)-1:]
switch postfix {
case "K":
multiplier = 1024.0
case "M":
multiplier = math.Pow(1024, 2)
case "G":
multiplier = math.Pow(1024, 3)
case "T":
multiplier = math.Pow(1024, 4)
case "P":
multiplier = math.Pow(1024, 5)
}

if multiplier >= 1.0 {
s = s[:len(s)-1]

if i, err := strconv.ParseInt(s, 10, 64); err == nil {
newValue := float64(i) * multiplier
if c.Bool("verbose") {
log.Printf("converting units, %v (%f)\n", object, newValue)
}

return newValue, true
}
}
}
}
return object.(string), true
}
}

if c.Bool("verbose") {
Expand Down Expand Up @@ -197,6 +294,10 @@ func getFields(kind string) []tableField {
title: "PHASE",
name: "status.phase",
},
{
title: "hostIP",
name: "status.hostIP",
},
{
title: "CREATION_TIME(RFC3339)",
name: "created",
Expand Down Expand Up @@ -269,7 +370,7 @@ func printItemsTable(c *cli.Context, items []unstructured.Unstructured) {

for _, field := range fields {
if field.width > 0 {
if value, found := evalFunc(field.name); found {
if value, found := evalFunc(field.name); found && value != nil {
fmt.Printf(field.template, value)
} else {
fmt.Printf(field.template, "")
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.13
require (
github.com/imdario/mergo v0.3.8 // indirect
github.com/urfave/cli/v2 v2.1.1
github.com/yaacov/tree-search-language/v5 v5.1.2
github.com/yaacov/tree-search-language/v5 v5.1.4
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
gopkg.in/yaml.v2 v2.2.8
Expand Down

0 comments on commit 1136625

Please sign in to comment.