diff --git a/cmd/kubectl-tree/status.go b/cmd/kubectl-tree/status.go index 6e10e5b..101bb64 100644 --- a/cmd/kubectl-tree/status.go +++ b/cmd/kubectl-tree/status.go @@ -5,45 +5,50 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/klog" + "sigs.k8s.io/cli-utils/pkg/kstatus/status" ) type ReadyStatus string // True False Unknown or "" type Reason string -func extractStatus(obj unstructured.Unstructured) (ReadyStatus, Reason) { +func extractStatus(obj unstructured.Unstructured) (ReadyStatus, Reason, status.Status) { jsonVal, _ := json.Marshal(obj.Object["status"]) klog.V(6).Infof("status for object=%s/%s: %s", obj.GetKind(), obj.GetName(), string(jsonVal)) + result, err := status.Compute(&obj) + if err != nil { + return "", "", "" + } statusF, ok := obj.Object["status"] if !ok { - return "", "" + return "", "", "" } statusV, ok := statusF.(map[string]interface{}) if !ok { - return "", "" + return "", "", "" } conditionsF, ok := statusV["conditions"] if !ok { - return "", "" + return "", "", "" } conditionsV, ok := conditionsF.([]interface{}) if !ok { - return "", "" + return "", "", "" } for _, cond := range conditionsV { condM, ok := cond.(map[string]interface{}) if !ok { - return "", "" + return "", "", "" } condType, ok := condM["type"].(string) if !ok { - return "", "" + return "", "", "" } if condType == "Ready" { condStatus, _ := condM["status"].(string) condReason, _ := condM["reason"].(string) - return ReadyStatus(condStatus), Reason(condReason) + return ReadyStatus(condStatus), Reason(condReason), status.Status(result.Status.String()) } } - return "", "" + return "", "", "" } diff --git a/cmd/kubectl-tree/tree.go b/cmd/kubectl-tree/tree.go index c2f8518..3988e08 100644 --- a/cmd/kubectl-tree/tree.go +++ b/cmd/kubectl-tree/tree.go @@ -10,6 +10,7 @@ import ( "github.com/gosuri/uitable" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/util/duration" + "sigs.k8s.io/cli-utils/pkg/kstatus/status" ) const ( @@ -20,22 +21,23 @@ const ( ) var ( - gray = color.New(color.FgHiBlack) - red = color.New(color.FgRed) - green = color.New(color.FgGreen) + gray = color.New(color.FgHiBlack) + red = color.New(color.FgRed) + yellow = color.New(color.FgYellow) + green = color.New(color.FgGreen) ) // treeView prints object hierarchy to out stream. func treeView(out io.Writer, objs objectDirectory, obj unstructured.Unstructured) { tbl := uitable.New() tbl.Separator = " " - tbl.AddRow("NAMESPACE", "NAME", "READY", "REASON", "AGE") + tbl.AddRow("NAMESPACE", "NAME", "READY", "REASON", "STATUS", "AGE") treeViewInner("", tbl, objs, obj) fmt.Fprintln(color.Output, tbl) } func treeViewInner(prefix string, tbl *uitable.Table, objs objectDirectory, obj unstructured.Unstructured) { - ready, reason := extractStatus(obj) + ready, reason, kstatus := extractStatus(obj) var readyColor *color.Color switch ready { @@ -50,6 +52,21 @@ func treeViewInner(prefix string, tbl *uitable.Table, objs objectDirectory, obj ready = "-" } + var statusColor *color.Color + switch kstatus { + case status.CurrentStatus: + statusColor = green + case status.InProgressStatus: + statusColor = yellow + case status.FailedStatus, status.TerminatingStatus: + statusColor = red + default: + statusColor = gray + } + if kstatus == "" { + kstatus = "-" + } + c := obj.GetCreationTimestamp() age := duration.HumanDuration(time.Since(c.Time)) if c.IsZero() { @@ -62,6 +79,7 @@ func treeViewInner(prefix string, tbl *uitable.Table, objs objectDirectory, obj color.New(color.Bold).Sprint(obj.GetName())), readyColor.Sprint(ready), readyColor.Sprint(reason), + statusColor.Sprint(kstatus), age) chs := objs.ownedBy(obj.GetUID()) for i, child := range chs { diff --git a/go.mod b/go.mod index 22da9eb..fd52224 100644 --- a/go.mod +++ b/go.mod @@ -5,12 +5,14 @@ go 1.20 require ( github.com/fatih/color v1.15.0 github.com/gosuri/uitable v0.0.4 + github.com/pkg/errors v0.9.1 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 k8s.io/apimachinery v0.27.4 k8s.io/cli-runtime v0.27.4 k8s.io/client-go v0.27.4 k8s.io/klog v1.0.0 + sigs.k8s.io/cli-utils v0.35.0 ) require ( @@ -31,7 +33,7 @@ require ( github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect - github.com/imdario/mergo v0.3.6 // indirect + github.com/imdario/mergo v0.3.12 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -45,7 +47,6 @@ require ( github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/xlab/treeprint v1.1.0 // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect @@ -54,7 +55,7 @@ require ( golang.org/x/sys v0.6.0 // indirect golang.org/x/term v0.6.0 // indirect golang.org/x/text v0.8.0 // indirect - golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect + golang.org/x/time v0.3.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/go.sum b/go.sum index e5d31bd..e6adf5c 100644 --- a/go.sum +++ b/go.sum @@ -142,8 +142,8 @@ github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:Fecb github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= -github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -352,8 +352,8 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -490,6 +490,7 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -522,6 +523,8 @@ k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/cli-utils v0.35.0 h1:dfSJaF1W0frW74PtjwiyoB4cwdRygbHnC7qe7HF0g/Y= +sigs.k8s.io/cli-utils v0.35.0/go.mod h1:ITitykCJxP1vaj1Cew/FZEaVJ2YsTN9Q71m02jebkoE= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/kustomize/api v0.13.2 h1:kejWfLeJhUsTGioDoFNJET5LQe/ajzXhJGYoU+pJsiA=