added yaml syntax color + secret decoding + bugz
parent
d72166ccbf
commit
8924f6002d
11
go.mod
11
go.mod
|
|
@ -3,12 +3,18 @@ module github.com/derailed/k9s
|
|||
require (
|
||||
contrib.go.opencensus.io/exporter/ocagent v0.4.3 // indirect
|
||||
github.com/Azure/go-autorest v11.4.0+incompatible // indirect
|
||||
github.com/MakeNowJust/heredoc v0.0.0-20171113091838-e9091a26100e // indirect
|
||||
github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1 // indirect
|
||||
github.com/derailed/tview v0.1.4
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
|
||||
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||
github.com/docker/docker v1.13.1 // indirect
|
||||
github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c // indirect
|
||||
github.com/evanphx/json-patch v4.1.0+incompatible // indirect
|
||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
|
||||
github.com/fatih/camelcase v1.0.0 // indirect
|
||||
github.com/gdamore/tcell v1.1.1
|
||||
github.com/go-openapi/spec v0.19.0 // indirect
|
||||
github.com/gogo/protobuf v1.1.1 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef // indirect
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c // indirect
|
||||
|
|
@ -21,6 +27,7 @@ require (
|
|||
github.com/json-iterator/go v1.1.5 // indirect
|
||||
github.com/kr/pretty v0.1.0 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.4
|
||||
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||
github.com/onsi/gomega v1.4.3 // indirect
|
||||
|
|
@ -29,6 +36,8 @@ require (
|
|||
github.com/petergtz/pegomock v0.0.0-20181206220228-b113d17a7e81
|
||||
github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967 // indirect
|
||||
github.com/rs/zerolog v1.12.0
|
||||
github.com/russross/blackfriday v2.0.0+incompatible // indirect
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
||||
github.com/sirupsen/logrus v1.4.0 // indirect
|
||||
github.com/spf13/cobra v0.0.3
|
||||
github.com/spf13/pflag v1.0.3 // indirect
|
||||
|
|
@ -51,5 +60,5 @@ require (
|
|||
k8s.io/metrics v0.0.0-20181121073115-d8618695b08f
|
||||
k8s.io/utils v0.0.0-20190212002617-cdba02414f76 // indirect
|
||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190130003954-e5e029740eb8 // indirect
|
||||
sigs.k8s.io/yaml v1.1.0 // indirect
|
||||
sigs.k8s.io/yaml v1.1.0
|
||||
)
|
||||
|
|
|
|||
31
go.sum
31
go.sum
|
|
@ -7,10 +7,18 @@ git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGy
|
|||
git.apache.org/thrift.git v0.0.0-20181218151757-9b75e4fe745a/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
github.com/Azure/go-autorest v11.4.0+incompatible h1:z3Yr6KYqs0nhSNwqGXEBpWK977hxVqsLv2n9PVYcixY=
|
||||
github.com/Azure/go-autorest v11.4.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/MakeNowJust/heredoc v0.0.0-20171113091838-e9091a26100e h1:eb0Pzkt15Bm7f2FFYv7sjY7NPFi3cPkS3tv1CcrFBWA=
|
||||
github.com/MakeNowJust/heredoc v0.0.0-20171113091838-e9091a26100e/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=
|
||||
github.com/PuerkitoBio/purell v1.1.0 h1:rmGxhojJlM0tuKtfdvliR84CFHljx9ag64t2xmVkjK4=
|
||||
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/census-instrumentation/opencensus-proto v0.1.0-0.20181214143942-ba49f56771b8 h1:gUqsFVdUKoRHNg8fkFd8gB5OOEa/g5EwlAHznb4zjbI=
|
||||
github.com/census-instrumentation/opencensus-proto v0.1.0-0.20181214143942-ba49f56771b8/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1 h1:HD4PLRzjuCVW79mQ0/pdsalOLHJ+FaEoqJLxfltpb2U=
|
||||
github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
|
@ -22,8 +30,14 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumC
|
|||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v1.13.1 h1:IkZjBSIc8hBjLpqeAbeE5mca5mNgeatLHBy3GO78BWo=
|
||||
github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c h1:ZfSZ3P3BedhKGUhzj7BQlPSU4OvT6tfOKe3DVHzOA7s=
|
||||
github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||
github.com/evanphx/json-patch v4.1.0+incompatible h1:K1MDoo4AZ4wU0GIU/fPmtZg7VpzLjCxu+UwBD1FvwOc=
|
||||
github.com/evanphx/json-patch v4.1.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM=
|
||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
|
||||
github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
|
||||
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
|
|
@ -33,6 +47,14 @@ github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo
|
|||
github.com/gdamore/tcell v1.1.1 h1:U73YL+jMem2XfhvaIUfPO6MpJawaG92B2funXVb9qLs=
|
||||
github.com/gdamore/tcell v1.1.1/go.mod h1:K1udHkiR3cOtlpKG5tZPD5XxrF7v2y7lDq7Whcj+xkQ=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-openapi/jsonpointer v0.17.0 h1:nH6xp8XdXHx8dqveo0ZuJBluCO2qGrPbDNZ0dwoRHP0=
|
||||
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
|
||||
github.com/go-openapi/jsonreference v0.17.0 h1:yJW3HCkTHg7NOA+gZ83IPHzUSnUzGXhGmsdiCcMexbA=
|
||||
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
|
||||
github.com/go-openapi/spec v0.19.0 h1:A4SZ6IWh3lnjH0rG0Z5lkxazMGBECtrZcbyYQi+64k4=
|
||||
github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
|
||||
github.com/go-openapi/swag v0.17.0 h1:iqrgMg7Q7SvtbWLlltPrkMs0UBJI6oTSs79JFRUi880=
|
||||
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
|
||||
github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
|
|
@ -77,10 +99,14 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lucasb-eyer/go-colorful v0.0.0-20181028223441-12d3b2882a08 h1:5MnxBC15uMxFv5FY/J/8vzyaBiArCOkMdFT9Jsw78iY=
|
||||
github.com/lucasb-eyer/go-colorful v0.0.0-20181028223441-12d3b2882a08/go.mod h1:NXg0ArsFk0Y01623LgUqoqcouGDB+PwCCQlrwrG6xJ4=
|
||||
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic=
|
||||
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
|
||||
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
|
|
@ -117,6 +143,10 @@ github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967 h1:x7xEyJDP7Hv3LVgvWhz
|
|||
github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
|
||||
github.com/rs/zerolog v1.12.0 h1:aqZ1XRadoS8IBknR5IDFvGzbHly1X9ApIqOroooQF/c=
|
||||
github.com/rs/zerolog v1.12.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/russross/blackfriday v2.0.0+incompatible h1:cBXrhZNUf9C+La9/YpS+UHpUT8YD6Td9ZMSU9APFcsk=
|
||||
github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.0 h1:yKenngtzGh+cUSSh6GWbxW2abRqhYUSR/t/6+2QqNvE=
|
||||
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
|
|
@ -139,6 +169,7 @@ golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTk
|
|||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181217023233-e147a9138326 h1:iCzOf0xz39Tstp+Tu/WwyGjUXCk34QhQORRxBeXXTA4=
|
||||
|
|
|
|||
|
|
@ -26,11 +26,6 @@ type detailsView struct {
|
|||
numSelections int
|
||||
}
|
||||
|
||||
var (
|
||||
regionRX = regexp.MustCompile(`\["([a-zA-Z0-9_,;: \-\.]*)"\]`)
|
||||
escapeRX = regexp.MustCompile(`\[([a-zA-Z0-9_,;: \-\."#]+)\[(\[*)\]`)
|
||||
)
|
||||
|
||||
func newDetailsView(app *appView, backFn actionHandler) *detailsView {
|
||||
v := detailsView{TextView: tview.NewTextView(), app: app, actions: make(keyActions)}
|
||||
{
|
||||
|
|
@ -53,8 +48,6 @@ func newDetailsView(app *appView, backFn actionHandler) *detailsView {
|
|||
})
|
||||
}
|
||||
|
||||
// v.actions[KeySlash] = newKeyAction("Search", v.activateCmd)
|
||||
// v.actions[tcell.KeyEnter] = newKeyAction("Search", v.searchCmd)
|
||||
v.actions[tcell.KeyBackspace2] = newKeyAction("Erase", v.eraseCmd, false)
|
||||
v.actions[tcell.KeyBackspace] = newKeyAction("Erase", v.eraseCmd, false)
|
||||
v.actions[tcell.KeyDelete] = newKeyAction("Erase", v.eraseCmd, false)
|
||||
|
|
@ -207,6 +200,11 @@ func (v *detailsView) setTitle(t string) {
|
|||
v.SetTitle(title)
|
||||
}
|
||||
|
||||
var (
|
||||
regionRX = regexp.MustCompile(`\["([a-zA-Z0-9_,;: \-\.]*)"\]`)
|
||||
escapeRX = regexp.MustCompile(`\[([a-zA-Z0-9_,;: \-\."#]+)\[(\[*)\]`)
|
||||
)
|
||||
|
||||
func (v *detailsView) decorateLines(buff, q string) string {
|
||||
rx := regexp.MustCompile(`(?i)` + q)
|
||||
lines := strings.Split(buff, "\n")
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ func newLogView(title string, parent loggable) *logView {
|
|||
}
|
||||
|
||||
func (l *logView) logLine(line string) {
|
||||
fmt.Fprintln(l.ansiWriter, line)
|
||||
fmt.Fprintln(l.ansiWriter, tview.Escape(line))
|
||||
}
|
||||
|
||||
func (l *logView) log(lines fmt.Stringer) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
package views
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/derailed/tview"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAnsi(t *testing.T) {
|
||||
buff := bytes.NewBufferString("")
|
||||
w := tview.ANSIWriter(buff)
|
||||
fmt.Fprintf(w, "[YELLOW] ok")
|
||||
assert.Equal(t, "[YELLOW] ok", buff.String())
|
||||
|
||||
v := tview.NewTextView()
|
||||
v.SetDynamicColors(true)
|
||||
aw := tview.ANSIWriter(v)
|
||||
s := "[2019-03-27T15:05:15,246][INFO ][o.e.c.r.a.AllocationService] [es-0] Cluster health status changed from [YELLOW] to [GREEN] (reason: [shards started [[.monitoring-es-6-2019.03.27][0]]"
|
||||
fmt.Fprintf(aw, s)
|
||||
assert.Equal(t, s+"\n", v.GetText(false))
|
||||
}
|
||||
|
|
@ -270,7 +270,7 @@ func resourceViews(c k8s.Connection) map[string]resCmd {
|
|||
"sec": {
|
||||
title: "Secrets",
|
||||
api: "",
|
||||
viewFn: newResourceView,
|
||||
viewFn: newSecretView,
|
||||
listFn: resource.NewSecretList,
|
||||
},
|
||||
"sts": {
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ func (v *resourceView) deleteCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
|
||||
func (v *resourceView) defaultEnter(app *appView, ns, resource, selection string) {
|
||||
sel := v.getSelectedItem()
|
||||
raw, err := v.list.Resource().Describe(v.title, sel, v.app.flags)
|
||||
yaml, err := v.list.Resource().Describe(v.title, sel, v.app.flags)
|
||||
if err != nil {
|
||||
v.app.flash(flashErr, err.Error())
|
||||
log.Warn().Msgf("Describe %v", err.Error())
|
||||
|
|
@ -202,7 +202,7 @@ func (v *resourceView) defaultEnter(app *appView, ns, resource, selection string
|
|||
details.setCategory("Describe")
|
||||
details.setTitle(sel)
|
||||
details.SetTextColor(tcell.ColorAqua)
|
||||
details.SetText(string(raw))
|
||||
details.SetText(colorizeYAML(yaml))
|
||||
details.ScrollToBeginning()
|
||||
}
|
||||
v.switchPage("details")
|
||||
|
|
@ -212,7 +212,6 @@ func (v *resourceView) describeCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
if !v.rowSelected() {
|
||||
return evt
|
||||
}
|
||||
|
||||
v.defaultEnter(v.app, v.list.GetNamespace(), v.list.GetName(), v.selectedItem)
|
||||
|
||||
return nil
|
||||
|
|
@ -234,7 +233,7 @@ func (v *resourceView) viewCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
details.setCategory("View")
|
||||
details.setTitle(sel)
|
||||
details.SetTextColor(tcell.ColorMediumAquamarine)
|
||||
details.SetText(string(raw))
|
||||
details.SetText(colorizeYAML(raw))
|
||||
details.ScrollToBeginning()
|
||||
}
|
||||
v.switchPage("details")
|
||||
|
|
@ -345,9 +344,12 @@ func (v *resourceView) switchPage(p string) {
|
|||
{
|
||||
v.SwitchToPage(p)
|
||||
v.selectedNS = v.list.GetNamespace()
|
||||
h := v.GetPrimitive(p).(hinter)
|
||||
v.app.setHints(h.hints())
|
||||
v.app.SetFocus(v.CurrentPage().Item)
|
||||
if h, ok := v.GetPrimitive(p).(hinter); ok {
|
||||
v.app.setHints(h.hints())
|
||||
v.app.SetFocus(v.CurrentPage().Item)
|
||||
} else {
|
||||
log.Error().Msgf("Hinter not implemented on %s", p)
|
||||
}
|
||||
}
|
||||
v.update.Unlock()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
package views
|
||||
|
||||
import (
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"github.com/derailed/k9s/internal/resource"
|
||||
"github.com/gdamore/tcell"
|
||||
"github.com/rs/zerolog/log"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
type secretView struct {
|
||||
*resourceView
|
||||
}
|
||||
|
||||
func newSecretView(t string, app *appView, list resource.List) resourceViewer {
|
||||
v := secretView{newResourceView(t, app, list).(*resourceView)}
|
||||
{
|
||||
v.extraActionsFn = v.extraActions
|
||||
v.switchPage("secret")
|
||||
}
|
||||
|
||||
return &v
|
||||
}
|
||||
|
||||
func (v *secretView) extraActions(aa keyActions) {
|
||||
aa[tcell.KeyCtrlX] = newKeyAction("Decode", v.decodeCmd, true)
|
||||
}
|
||||
|
||||
func (v *secretView) decodeCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||
if !v.rowSelected() {
|
||||
return evt
|
||||
}
|
||||
|
||||
sel := v.getSelectedItem()
|
||||
ns, n := namespaced(sel)
|
||||
sec, err := v.app.conn().DialOrDie().CoreV1().Secrets(ns).Get(n, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
v.app.flash(flashErr, "Unable to retrieve secret", sel)
|
||||
return evt
|
||||
}
|
||||
|
||||
d := make(map[string]string, len(sec.Data))
|
||||
for k, val := range sec.Data {
|
||||
d[k] = string(val)
|
||||
}
|
||||
raw, err := yaml.Marshal(d)
|
||||
if err != nil {
|
||||
v.app.flash(flashErr, "Error decoding secret for `", sel)
|
||||
log.Error().Err(err).Msgf("Marshal error getting secret %s", sel)
|
||||
return nil
|
||||
}
|
||||
|
||||
details := v.GetPrimitive("details").(*detailsView)
|
||||
{
|
||||
details.setCategory("Decoder")
|
||||
details.setTitle(sel)
|
||||
details.SetTextColor(tcell.ColorMediumAquamarine)
|
||||
details.SetText(colorizeYAML(string(raw)))
|
||||
details.ScrollToBeginning()
|
||||
}
|
||||
v.switchPage("details")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -4,8 +4,10 @@ import (
|
|||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/derailed/k9s/internal/resource"
|
||||
res "k8s.io/apimachinery/pkg/api/resource"
|
||||
)
|
||||
|
||||
type rowSorter struct {
|
||||
|
|
@ -53,6 +55,10 @@ func less(asc bool, c1, c2 string) bool {
|
|||
return o
|
||||
}
|
||||
|
||||
if o, ok := isDurationSort(asc, c1, c2); ok {
|
||||
return o
|
||||
}
|
||||
|
||||
if o, ok := isIntegerSort(asc, c1, c2); ok {
|
||||
return o
|
||||
}
|
||||
|
|
@ -64,18 +70,30 @@ func less(asc bool, c1, c2 string) bool {
|
|||
return c > 0
|
||||
}
|
||||
|
||||
func isMetricSort(asc bool, c1, c2 string) (bool, bool) {
|
||||
m1, ok := isMetric(c1)
|
||||
if !ok {
|
||||
func isDurationSort(asc bool, c1, c2 string) (bool, bool) {
|
||||
d1, ok1 := isDuration(c1)
|
||||
d2, ok2 := isDuration(c2)
|
||||
if !ok1 || !ok2 {
|
||||
return false, false
|
||||
}
|
||||
m2, _ := isMetric(c2)
|
||||
i1, _ := strconv.Atoi(m1)
|
||||
i2, _ := strconv.Atoi(m2)
|
||||
|
||||
if asc {
|
||||
return i1 < i2, true
|
||||
return d1 < d2, true
|
||||
}
|
||||
return i1 > i2, true
|
||||
return d1 > d2, true
|
||||
}
|
||||
|
||||
func isMetricSort(asc bool, c1, c2 string) (bool, bool) {
|
||||
q1, err1 := res.ParseQuantity(c1)
|
||||
q2, err2 := res.ParseQuantity(c2)
|
||||
if err1 != nil || err2 != nil {
|
||||
return false, false
|
||||
}
|
||||
|
||||
if asc {
|
||||
return q1.Cmp(q2) <= 0, true
|
||||
}
|
||||
return q1.Cmp(q2) > 0, true
|
||||
}
|
||||
|
||||
func isIntegerSort(asc bool, c1, c2 string) (bool, bool) {
|
||||
|
|
@ -98,3 +116,11 @@ func isMetric(s string) (string, bool) {
|
|||
}
|
||||
return s, false
|
||||
}
|
||||
|
||||
func isDuration(s string) (time.Duration, bool) {
|
||||
d, err := time.ParseDuration(s)
|
||||
if err != nil {
|
||||
return d, false
|
||||
}
|
||||
return d, true
|
||||
}
|
||||
|
|
@ -22,6 +22,8 @@ func TestGroupSort(t *testing.T) {
|
|||
{false, []string{"100Mi", "10Mi"}, []string{"100Mi", "10Mi"}},
|
||||
{true, []string{"xyz", "abc"}, []string{"abc", "xyz"}},
|
||||
{false, []string{"xyz", "abc"}, []string{"xyz", "abc"}},
|
||||
{true, []string{"2m30s", "1m10s"}, []string{"1m10s", "2m30s"}},
|
||||
{true, []string{"3d", "1d"}, []string{"1d", "3d"}},
|
||||
}
|
||||
|
||||
for _, u := range uu {
|
||||
|
|
@ -33,9 +35,8 @@ func TestGroupSort(t *testing.T) {
|
|||
|
||||
func TestRowSort(t *testing.T) {
|
||||
uu := []struct {
|
||||
order bool
|
||||
rows resource.Rows
|
||||
expect resource.Rows
|
||||
order bool
|
||||
rows, expect resource.Rows
|
||||
}{
|
||||
{
|
||||
true,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
package views
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
keyValRX = regexp.MustCompile(`\A(\s*)([\w|\-|\.|\s]+):\s(.+)\z`)
|
||||
keyRX = regexp.MustCompile(`\A(\s*)([\w|\-|\.|\s]+):\s*\z`)
|
||||
)
|
||||
|
||||
func colorizeYAML(raw string) string {
|
||||
lines := strings.Split(raw, "\n")
|
||||
|
||||
buff := make([]string, 0, len(lines))
|
||||
for _, l := range lines {
|
||||
res := keyValRX.FindStringSubmatch(l)
|
||||
if len(res) == 4 {
|
||||
buff = append(buff, fmt.Sprintf("%s[steelblue::b]%s[white::-]: [papayawhip::]%s", res[1], res[2], res[3]))
|
||||
continue
|
||||
}
|
||||
|
||||
res = keyRX.FindStringSubmatch(l)
|
||||
if len(res) == 3 {
|
||||
buff = append(buff, fmt.Sprintf("%s[steelblue::b]%s[white::-]:", res[1], res[2]))
|
||||
continue
|
||||
}
|
||||
|
||||
buff = append(buff, fmt.Sprintf("[papayawhip::]%s", l))
|
||||
}
|
||||
|
||||
return strings.Join(buff, "\n")
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package views
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestYaml(t *testing.T) {
|
||||
uu := []struct {
|
||||
s, e string
|
||||
}{
|
||||
{
|
||||
`api: fred
|
||||
version: v1`,
|
||||
`[steelblue::b]api[white::-]: [papayawhip::]fred
|
||||
[steelblue::b]version[white::-]: [papayawhip::]v1`,
|
||||
},
|
||||
{
|
||||
`api:
|
||||
version: v1`,
|
||||
`[steelblue::b]api[white::-]:
|
||||
[steelblue::b]version[white::-]: [papayawhip::]v1`,
|
||||
},
|
||||
{
|
||||
" fred:blee",
|
||||
"[papayawhip::] fred:blee",
|
||||
},
|
||||
{
|
||||
"fred blee: blee",
|
||||
"[steelblue::b]fred blee[white::-]: [papayawhip::]blee",
|
||||
},
|
||||
{
|
||||
"Node-Selectors: <none>",
|
||||
"[steelblue::b]Node-Selectors[white::-]: [papayawhip::] <none>",
|
||||
},
|
||||
{
|
||||
"fred.blee: <none>",
|
||||
"[steelblue::b]fred.blee[white::-]: [papayawhip::] <none>",
|
||||
},
|
||||
}
|
||||
|
||||
for _, u := range uu {
|
||||
assert.Equal(t, u.e, colorizeYAML(u.s))
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue