From 57a9079dae264ba2bed5b187475263a9954d43c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Feb 2023 11:36:30 -0700 Subject: [PATCH 01/14] Bump helm.sh/helm/v3 from 3.11.0 to 3.11.1 (#1963) Bumps [helm.sh/helm/v3](https://github.com/helm/helm) from 3.11.0 to 3.11.1. - [Release notes](https://github.com/helm/helm/releases) - [Commits](https://github.com/helm/helm/compare/v3.11.0...v3.11.1) --- updated-dependencies: - dependency-name: helm.sh/helm/v3 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 4c544084c7..026022bed9 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/stretchr/testify v1.8.1 golang.org/x/text v0.6.0 gopkg.in/yaml.v2 v2.4.0 - helm.sh/helm/v3 v3.11.0 + helm.sh/helm/v3 v3.11.1 k8s.io/api v0.26.1 k8s.io/apiextensions-apiserver v0.26.1 k8s.io/apimachinery v0.26.1 diff --git a/go.sum b/go.sum index 4a99afd2e0..86c29641c4 100644 --- a/go.sum +++ b/go.sum @@ -547,10 +547,10 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rubenv/sql-migrate v1.2.0 h1:fOXMPLMd41sK7Tg75SXDec15k3zg5WNV6SjuDRiNfcU= -github.com/rubenv/sql-migrate v1.2.0/go.mod h1:Z5uVnq7vrIrPmHbVFfR4YLHRZquxeHpckCnRq0P/K9Y= github.com/rs/zerolog v1.29.0 h1:Zes4hju04hjbvkVkOhdl2HpZa+0PmVwigmo8XoORE5w= github.com/rs/zerolog v1.29.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= +github.com/rubenv/sql-migrate v1.2.0 h1:fOXMPLMd41sK7Tg75SXDec15k3zg5WNV6SjuDRiNfcU= +github.com/rubenv/sql-migrate v1.2.0/go.mod h1:Z5uVnq7vrIrPmHbVFfR4YLHRZquxeHpckCnRq0P/K9Y= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -1060,8 +1060,8 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= -helm.sh/helm/v3 v3.11.0 h1:F+peaCQYbycY1FIqIQ6dAortHd/VzV5FkhMciv4Kf+c= -helm.sh/helm/v3 v3.11.0/go.mod h1:z/Bu/BylToGno/6dtNGuSmjRqxKq5gaH+FU0BPO+AQ8= +helm.sh/helm/v3 v3.11.1 h1:cmL9fFohOoNQf+wnp2Wa0OhNFH0KFnSzEkVxi3fcc3I= +helm.sh/helm/v3 v3.11.1/go.mod h1:z/Bu/BylToGno/6dtNGuSmjRqxKq5gaH+FU0BPO+AQ8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From a9c61040a9f1110f5f854323f8e6714b43ecf11e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Ni=C3=B1o=20D=C3=ADaz?= Date: Sat, 11 Feb 2023 18:42:26 +0000 Subject: [PATCH 02/14] fix: Add missing help menu to gruvbox-dark skin (#1969) The values of almost everything in the skins gruvbox-light and gruvbox-dark are the same, but gruvbox-dark is missing the values of the help menu, which looks a bit broken. This patch copies the values from gruvbox-light to gruvbox-dark so that it looks fine. --- skins/gruvbox-dark.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/skins/gruvbox-dark.yml b/skins/gruvbox-dark.yml index b697b3ddf0..99d6961593 100644 --- a/skins/gruvbox-dark.yml +++ b/skins/gruvbox-dark.yml @@ -23,6 +23,12 @@ k9s: info: fgColor: *magenta sectionColor: *foreground + help: + fgColor: *foreground + bgColor: *background + keyColor: *magenta + numKeyColor: *blue + sectionColor: *green dialog: fgColor: *foreground bgColor: *background From ba84123d8ee7657cd2e81f5e257b00eec7d15df4 Mon Sep 17 00:00:00 2001 From: Ivar Stangeby Date: Sat, 11 Feb 2023 19:44:21 +0100 Subject: [PATCH 03/14] Added Nightfox theme (#1960) --- skins/nightfox.yml | 96 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 skins/nightfox.yml diff --git a/skins/nightfox.yml b/skins/nightfox.yml new file mode 100644 index 0000000000..f072b47b41 --- /dev/null +++ b/skins/nightfox.yml @@ -0,0 +1,96 @@ +# K9s Nightfox Theme +# Based on the Nightfox.nvim color scheme: +# https://github.com/EdenEast/nightfox.nvim +foreground: &foreground "#cdcecf" +background: &background "#192330" +current_line: ¤t_line "#2b3b51" +selection: &selection "#2b3b51" +comment: &comment "#738091" +cyan: &cyan "#63cdcf" +green: &green "#81b29a" +orange: &orange "#f4a261" +magenta: &magenta "#9d79d6" +blue: &blue "#719cd6" +red: &red "#c94f6d" + +k9s: + body: + fgColor: *foreground + bgColor: *background + logoColor: *blue + prompt: + fgColor: *foreground + bgColor: *background + suggestColor: *orange + info: + fgColor: *magenta + sectionColor: *foreground + dialog: + fgColor: *foreground + bgColor: *background + buttonFgColor: *foreground + buttonBgColor: *magenta + buttonFocusFgColor: white + buttonFocusBgColor: *cyan + labelFgColor: *orange + fieldFgColor: *foreground + frame: + border: + fgColor: *selection + focusColor: *current_line + menu: + fgColor: *foreground + keyColor: *magenta + numKeyColor: *magenta + crumbs: + fgColor: *foreground + bgColor: *current_line + activeColor: *current_line + status: + newColor: *cyan + modifyColor: *blue + addColor: *green + errorColor: *red + highlightColor: *orange + killColor: *comment + completedColor: *comment + title: + fgColor: *foreground + bgColor: *current_line + highlightColor: *orange + counterColor: *blue + filterColor: *magenta + views: + charts: + bgColor: default + defaultDialColors: + - *blue + - *red + defaultChartColors: + - *blue + - *red + table: + fgColor: *foreground + bgColor: *background + cursorFgColor: *selection + cursorBgColor: *current_line + header: + fgColor: *foreground + bgColor: *background + sorterColor: *cyan + xray: + fgColor: *foreground + bgColor: *background + cursorColor: *current_line + graphicColor: *blue + showIcons: false + yaml: + keyColor: *magenta + colonColor: *blue + valueColor: *foreground + logs: + fgColor: *foreground + bgColor: *background + indicator: + fgColor: *foreground + bgColor: *selection From f694a63d98d06fe7b59b975bd9e45959d6009202 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Feb 2023 11:44:46 -0700 Subject: [PATCH 04/14] Bump github.com/fatih/color from 1.13.0 to 1.14.1 (#1959) Bumps [github.com/fatih/color](https://github.com/fatih/color) from 1.13.0 to 1.14.1. - [Release notes](https://github.com/fatih/color/releases) - [Commits](https://github.com/fatih/color/compare/v1.13.0...v1.14.1) --- updated-dependencies: - dependency-name: github.com/fatih/color dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 10 ++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 026022bed9..f6fc501abc 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/derailed/popeye v0.10.1 github.com/derailed/tcell/v2 v2.3.1-rc.3 github.com/derailed/tview v0.8.1 - github.com/fatih/color v1.13.0 + github.com/fatih/color v1.14.1 github.com/fsnotify/fsnotify v1.6.0 github.com/fvbommel/sortorder v1.0.2 github.com/ghodss/yaml v1.0.0 @@ -96,7 +96,7 @@ require ( github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mailru/easyjson v0.7.6 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-wordwrap v1.0.0 // indirect diff --git a/go.sum b/go.sum index 86c29641c4..6a0356e4a5 100644 --- a/go.sum +++ b/go.sum @@ -165,8 +165,8 @@ github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZM 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/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -412,15 +412,14 @@ github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2 github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= @@ -790,7 +789,6 @@ golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From ec8a272e8928f03be66cf20bdd582329a53186eb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Feb 2023 11:45:18 -0700 Subject: [PATCH 05/14] Bump golang from 1.19.5-alpine3.16 to 1.20.0-alpine3.16 (#1956) Bumps golang from 1.19.5-alpine3.16 to 1.20.0-alpine3.16. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 8cf3a0d3d9..d77ed5b788 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # ----------------------------------------------------------------------------- # The base image for building the k9s binary -FROM golang:1.19.5-alpine3.16 AS build +FROM golang:1.20.0-alpine3.16 AS build WORKDIR /k9s COPY go.mod go.sum main.go Makefile ./ From 1cfeb582f0314da658077fa8e53f7442b287b6b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Feb 2023 11:45:37 -0700 Subject: [PATCH 06/14] Bump k8s.io/klog/v2 from 2.80.1 to 2.90.0 (#1958) Bumps [k8s.io/klog/v2](https://github.com/kubernetes/klog) from 2.80.1 to 2.90.0. - [Release notes](https://github.com/kubernetes/klog/releases) - [Changelog](https://github.com/kubernetes/klog/blob/main/RELEASE.md) - [Commits](https://github.com/kubernetes/klog/compare/v2.80.1...v2.90.0) --- updated-dependencies: - dependency-name: k8s.io/klog/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f6fc501abc..f3b22a5a81 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( k8s.io/apimachinery v0.26.1 k8s.io/cli-runtime v0.26.1 k8s.io/client-go v0.26.1 - k8s.io/klog/v2 v2.80.1 + k8s.io/klog/v2 v2.90.0 k8s.io/kubectl v0.26.1 k8s.io/metrics v0.26.1 sigs.k8s.io/yaml v1.3.0 diff --git a/go.sum b/go.sum index 6a0356e4a5..9f28436dde 100644 --- a/go.sum +++ b/go.sum @@ -1081,8 +1081,8 @@ k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU= k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE= k8s.io/component-base v0.26.1 h1:4ahudpeQXHZL5kko+iDHqLj/FSGAEUnSVO0EBbgDd+4= k8s.io/component-base v0.26.1/go.mod h1:VHrLR0b58oC035w6YQiBSbtsf0ThuSwXP+p5dD/kAWU= -k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= -k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.90.0 h1:VkTxIV/FjRXn1fgNNcKGM8cfmL1Z33ZjXRTVxKCoF5M= +k8s.io/klog/v2 v2.90.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= k8s.io/kubectl v0.26.1 h1:K8A0Jjlwg8GqrxOXxAbjY5xtmXYeYjLU96cHp2WMQ7s= From a25da1f5c67033a4600d74afdd66912b6d5c8065 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Feb 2023 11:45:56 -0700 Subject: [PATCH 07/14] Bump github.com/cenkalti/backoff/v4 from 4.1.3 to 4.2.0 (#1957) Bumps [github.com/cenkalti/backoff/v4](https://github.com/cenkalti/backoff) from 4.1.3 to 4.2.0. - [Release notes](https://github.com/cenkalti/backoff/releases) - [Commits](https://github.com/cenkalti/backoff/compare/v4.1.3...v4.2.0) --- updated-dependencies: - dependency-name: github.com/cenkalti/backoff/v4 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f3b22a5a81..ff1548e1af 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.19 require ( github.com/adrg/xdg v0.4.0 github.com/atotto/clipboard v0.1.4 - github.com/cenkalti/backoff/v4 v4.1.3 + github.com/cenkalti/backoff/v4 v4.2.0 github.com/derailed/popeye v0.10.1 github.com/derailed/tcell/v2 v2.3.1-rc.3 github.com/derailed/tview v0.8.1 diff --git a/go.sum b/go.sum index 9f28436dde..9652caf1bd 100644 --- a/go.sum +++ b/go.sum @@ -88,8 +88,8 @@ github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuP github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd h1:rFt+Y/IK1aEZkEHchZRSq9OQbsSzIT/OrI8YFFmRIng= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= -github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= -github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4= +github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= From 7ca8ad8ceaa54e64c9fe220874534cc176f36f5f Mon Sep 17 00:00:00 2001 From: Wolfgang Ebner Date: Sat, 11 Feb 2023 19:50:12 +0100 Subject: [PATCH 08/14] Match ${XXX} environment variables (#1896) --- README.md | 2 ++ internal/view/env.go | 37 ++++++++++++++++++++++++------------- internal/view/env_test.go | 36 +++++++++++++++++++++++++++++------- 3 files changed, 55 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 97c83d4c64..b632851eb6 100644 --- a/README.md +++ b/README.md @@ -579,6 +579,8 @@ K9s does provide additional environment variables for you to customize your plug * `$POD` while in a container view * `$COL-` use a given column name for a viewed resource. Must be prefixed by `COL-`! +Curly braces can be used to embed an environment variable inside another string, or if the column name contains special characters. (e.g. `${NAME}-example` or `${COL-%CPU/L}`) + ### Example This defines a plugin for viewing logs on a selected pod using `ctrl-l` for shortcut. diff --git a/internal/view/env.go b/internal/view/env.go index faf95c0d03..733beefe0f 100644 --- a/internal/view/env.go +++ b/internal/view/env.go @@ -13,30 +13,41 @@ import ( // Env represent K9s and K8s available environment variables. type Env map[string]string -// EnvRX match $XXX custom arg. -var envRX = regexp.MustCompile(`\$(\!?[\w|\d|\-|]+)`) +// EnvRX match $XXX, $!XXX, ${XXX} or ${!XXX} custom arg. +// | +// | (g2)(group 3) (g5)( group 6 ) +// | ( group 1 ) ( group 4 ) +// | ( group 0 ) +var envRX = regexp.MustCompile(`(\$(!?)([\w\-]+))|(\$\{(!?)([\w\-%/: ]+)})`) + +// keyFromSubmatch extracts the name and inverse flag of a match. +func keyFromSubmatch(m []string) (key string, inverse bool) { + // group 1 matches $XXX and $!XXX args. + if m[1] != "" { + return m[3], m[2] == "!" + } + // group 4 matches ${XXX} and ${!XXX} args. + return m[6], m[5] == "!" +} // Substitute replaces env variable keys from in a string with their corresponding values. func (e Env) Substitute(arg string) (string, error) { - kk := envRX.FindAllString(arg, -1) - if len(kk) == 0 { + matches := envRX.FindAllStringSubmatch(arg, -1) + if len(matches) == 0 { return arg, nil } // To prevent the substitution starts with the shorter environment variable, // sort with the length of the found environment variables. - sort.Slice(kk, func(i, j int) bool { - return len(kk[i]) > len(kk[j]) + sort.Slice(matches, func(i, j int) bool { + return len(matches[i][0]) > len(matches[j][0]) }) - for _, k := range kk { - key, inverse := k[1:], false - if key[0] == '!' { - key, inverse = key[1:], true - } + for _, m := range matches { + key, inverse := keyFromSubmatch(m) v, ok := e[strings.ToUpper(key)] if !ok { - log.Warn().Msgf("no k9s environment matching key %q:%q", k, key) + log.Warn().Msgf("no k9s environment matching key %q:%q", m[0], key) continue } if b, err := strconv.ParseBool(v); err == nil { @@ -45,7 +56,7 @@ func (e Env) Substitute(arg string) (string, error) { } v = fmt.Sprintf("%t", b) } - arg = strings.Replace(arg, k, v, -1) + arg = strings.Replace(arg, m[0], v, -1) } return arg, nil diff --git a/internal/view/env_test.go b/internal/view/env_test.go index 313dde029f..2dab6cb7dd 100644 --- a/internal/view/env_test.go +++ b/internal/view/env_test.go @@ -19,20 +19,42 @@ func TestEnvReplace(t *testing.T) { "noMatch": {arg: "blah blah and $BLEE", e: "blah blah and $BLEE"}, "lower": {arg: "And then $b happened", e: "And then blee happened"}, "dash": {arg: "$col0", e: "fred"}, + "underline": {arg: "$RESOURCE_GROUP", e: "foo"}, "mix": {arg: "$col0 and then $a but $B", e: "fred and then 10 but blee"}, "subs": {arg: `{"spec" : {"suspend" : $COL0 }}`, e: `{"spec" : {"suspend" : fred }}`}, "boolean": {arg: "$COL-BOOL", e: "false"}, "invert": {arg: "$!COL-BOOL", e: "true"}, + + "simple_braces": {arg: "${A}", e: "10"}, + "embed_braces": {arg: "blabla${A}blabla", e: "blabla10blabla"}, + "open_braces": {arg: "${A", e: "${A"}, + "closed_braces": {arg: "$A}", e: "10}"}, + "substring_braces": {arg: "${A} and ${AA}", e: "10 and 20"}, + "with-text_braces": {arg: "Something ${A}", e: "Something 10"}, + "noMatch_braces": {arg: "blah blah and ${BLEE}", e: "blah blah and ${BLEE}"}, + "lower_braces": {arg: "And then ${b} happened", e: "And then blee happened"}, + "dash_braces": {arg: "${col0}", e: "fred"}, + "underline_braces": {arg: "${RESOURCE_GROUP}", e: "foo"}, + "mix_braces": {arg: "${col0} and then ${a} but ${B}", e: "fred and then 10 but blee"}, + "subs_braces": {arg: `{"spec" : {"suspend" : ${COL0} }}`, e: `{"spec" : {"suspend" : fred }}`}, + "boolean_braces": {arg: "${COL-BOOL}", e: "false"}, + "invert_braces": {arg: "${!COL-BOOL}", e: "true"}, + "special_braces": {arg: "${COL-%CPU/L}/${COL-MEM/R:L}", e: "10/32:32"}, + "space_braces": {arg: "${READINESS GATES}", e: "bar"}, } e := Env{ - "A": "10", - "AA": "20", - "B": "blee", - "COL0": "fred", - "FRED": "fred", - "COL-NAME": "zorg", - "COL-BOOL": "false", + "A": "10", + "AA": "20", + "B": "blee", + "COL0": "fred", + "FRED": "fred", + "COL-NAME": "zorg", + "COL-BOOL": "false", + "COL-%CPU/L": "10", + "COL-MEM/R:L": "32:32", + "RESOURCE_GROUP": "foo", + "READINESS GATES": "bar", } for k := range uu { From 0d7678babc565be8df80bc0a1ab7c8dc9a148deb Mon Sep 17 00:00:00 2001 From: Andrew Spiers <7andrew@gmail.com> Date: Sun, 12 Feb 2023 05:20:46 +1030 Subject: [PATCH 09/14] set default sinceSeconds to 300 (#1965) --- internal/config/config_test.go | 4 ++-- internal/config/logger.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 801992d03e..3821fd4589 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -290,7 +290,7 @@ var expectedConfig = `k9s: logger: tail: 500 buffer: 800 - sinceSeconds: 60 + sinceSeconds: 300 fullScreenLogs: false textWrap: false showTime: false @@ -389,7 +389,7 @@ var resetConfig = `k9s: logger: tail: 200 buffer: 2000 - sinceSeconds: 60 + sinceSeconds: 300 fullScreenLogs: false textWrap: false showTime: false diff --git a/internal/config/logger.go b/internal/config/logger.go index 11a59f5231..ba8c163887 100644 --- a/internal/config/logger.go +++ b/internal/config/logger.go @@ -10,7 +10,7 @@ const ( // MaxLogThreshold sets the max value for log size. MaxLogThreshold = 5000 // DefaultSinceSeconds tracks default log age. - DefaultSinceSeconds = 60 // all logs + DefaultSinceSeconds = 300 // all logs ) // Logger tracks logger options. From 2d2baa884a2a0cdd233b637c6fc6cacf3c4effbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Ni=C3=B1o=20D=C3=ADaz?= Date: Sat, 11 Feb 2023 18:51:11 +0000 Subject: [PATCH 10/14] fix: Show meaningful error message when kubectl exec fails (#1966) `exec.LookPath()` and `exec.Command()` aren't supposed to work with binaries that are located in the current working directory: https://cs.opensource.google/go/go/+/fd208c8850cdfe84469d3e4ef9bd55e2e0cece70:src/os/exec/exec.go If `kubectl` is found in the current working directory, `LookPath()` will return `ErrDot` even if it is also found in any other directory in the `PATH`. This patch detects this condition and shows a meaningful error message in the log so that the user knows the reason why `kubectl` couldn't be executed. Related: https://github.com/derailed/k9s/issues/1787 --- internal/view/exec.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/internal/view/exec.go b/internal/view/exec.go index 7724dc56ee..95a95035c0 100644 --- a/internal/view/exec.go +++ b/internal/view/exec.go @@ -41,6 +41,10 @@ type shellOpts struct { func runK(a *App, opts shellOpts) bool { bin, err := exec.LookPath("kubectl") + if errors.Is(err, exec.ErrDot) { + log.Error().Err(err).Msgf("kubectl command must not be in the current working directory") + return false + } if err != nil { log.Error().Err(err).Msgf("kubectl command is not in your path") return false @@ -137,6 +141,10 @@ func execute(opts shellOpts) error { func runKu(a *App, opts shellOpts) (string, error) { bin, err := exec.LookPath("kubectl") + if errors.Is(err, exec.ErrDot) { + log.Error().Err(err).Msgf("kubectl command must not be in the current working directory") + return "", err + } if err != nil { log.Error().Err(err).Msgf("kubectl command is not in your path") return "", err From d4ae1c7a744698ad981552f3ec25d00600794a74 Mon Sep 17 00:00:00 2001 From: Niko Janceski Date: Sat, 11 Feb 2023 13:51:29 -0500 Subject: [PATCH 11/14] Add sort by pod count on node view (#1961) --- internal/view/node.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/view/node.go b/internal/view/node.go index 6039fd8a6d..a025de51f0 100644 --- a/internal/view/node.go +++ b/internal/view/node.go @@ -57,6 +57,7 @@ func (n *Node) bindKeys(aa ui.KeyActions) { ui.KeyY: ui.NewKeyAction("YAML", n.yamlCmd, true), ui.KeyShiftC: ui.NewKeyAction("Sort CPU", n.GetTable().SortColCmd(cpuCol, false), false), ui.KeyShiftM: ui.NewKeyAction("Sort MEM", n.GetTable().SortColCmd(memCol, false), false), + ui.KeyShift0: ui.NewKeyAction("Sort Pods", n.GetTable().SortColCmd("PODS", false), false), }) } From 7c76691c389e4e7de29516932a304f7029307c6d Mon Sep 17 00:00:00 2001 From: Fernand Galiana Date: Sun, 12 Feb 2023 08:12:25 -0700 Subject: [PATCH 12/14] Release v0.27.3 (#1970) - [Issue #1968](https://github.com/derailed/k9s/issues/1968) Some skins are missing the definitions for the help menu - [Issue #1967](https://github.com/derailed/k9s/issues/1967) Helm cve-2023-25165 - [Issue #1964](https://github.com/derailed/k9s/issues/1964) logger.sinceSeconds config setting inconsistent with README - [Issue #1955](https://github.com/derailed/k9s/issues/1955) K9s crashes with empty resources and/or verbs in RBAC - [Issue #1954](https://github.com/derailed/k9s/issues/1954) Open very slow - [Issue #1883](https://github.com/derailed/k9s/issues/1883) Fix force deletion - [Issue #1788](https://github.com/derailed/k9s/issues/1788) Draining nodes cannot be forced - [Issue #1150](https://github.com/derailed/k9s/issues/1150) Add a persistent popup for drain failures --- Makefile | 2 +- README.md | 2 +- change_logs/release_v0.27.3.md | 67 ++++++++++++++++++++++++++++++ cmd/info.go | 7 +++- internal/dao/benchmark.go | 2 +- internal/dao/generic.go | 27 ++++++++---- internal/dao/helm.go | 2 +- internal/dao/node.go | 1 + internal/dao/port_forward.go | 2 +- internal/dao/screen_dump.go | 2 +- internal/dao/types.go | 2 +- internal/model/table.go | 4 +- internal/render/policy.go | 3 ++ internal/ui/dialog/confirm.go | 20 ++++----- internal/ui/dialog/confirm_test.go | 6 +-- internal/ui/dialog/delete.go | 31 ++++++-------- internal/ui/dialog/delete_test.go | 6 +-- internal/ui/dialog/error.go | 14 +++---- internal/ui/dialog/error_test.go | 21 ++++++++++ internal/ui/table_test.go | 3 +- internal/ui/types.go | 3 +- internal/view/alias_test.go | 3 +- internal/view/browser.go | 31 +++++++++++++- internal/view/details.go | 5 +++ internal/view/help.go | 1 - internal/view/node.go | 34 +++++++-------- internal/view/pf.go | 2 +- internal/view/pod.go | 2 +- internal/view/table_int_test.go | 3 +- internal/view/xray.go | 6 ++- 30 files changed, 225 insertions(+), 89 deletions(-) create mode 100644 change_logs/release_v0.27.3.md create mode 100644 internal/ui/dialog/error_test.go diff --git a/Makefile b/Makefile index cda1763f8f..3a6c7e0e8f 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ DATE ?= $(shell TZ=UTC date -j -f "%s" ${SOURCE_DATE_EPOCH} +"%Y-%m-%dT%H: else DATE ?= $(shell date -u -d @${SOURCE_DATE_EPOCH} +"%Y-%m-%dT%H:%M:%SZ") endif -VERSION ?= v0.27.2 +VERSION ?= v0.27.3 IMG_NAME := derailed/k9s IMAGE := ${IMG_NAME}:${VERSION} diff --git a/README.md b/README.md index b632851eb6..c4fdc8eeae 100644 --- a/README.md +++ b/README.md @@ -258,7 +258,7 @@ K9s uses aliases to navigate most K8s resources. | To view and switch to another Kubernetes namespace | `:`ns⏎ | | | To view all saved resources | `:`screendump or sd⏎ | | | To delete a resource (TAB and ENTER to confirm) | `ctrl-d` | | -| To kill a resource (no confirmation dialog!) | `ctrl-k` | | +| To kill a resource (no confirmation dialog, equivalent to kubectl delete --now) | `ctrl-k` | | | Launch pulses view | `:`pulses or pu⏎ | | | Launch XRay view | `:`xray RESOURCE [NAMESPACE]⏎ | RESOURCE can be one of po, svc, dp, rs, sts, ds, NAMESPACE is optional | | Launch Popeye view | `:`popeye or pop⏎ | See [popeye](#popeye) | diff --git a/change_logs/release_v0.27.3.md b/change_logs/release_v0.27.3.md new file mode 100644 index 0000000000..7c790f5f4c --- /dev/null +++ b/change_logs/release_v0.27.3.md @@ -0,0 +1,67 @@ + + +# Release v0.27.3 + +## Notes + +Thank you to all that contributed with flushing out issues and enhancements for K9s! I'll try to mark some of these issues as fixed. But if you don't mind grab the latest rev and see if we're happier with some of the fixes! If you've filed an issue please help me verify and close. Your support, kindness and awesome suggestions to make K9s better are, as ever, very much noted and appreciated! Also big thanks to all that have allocated their own time to help others on both slack and on this repo!! + +As you may know, K9s is not pimped out by corps with deep pockets, thus if you feel K9s is helping your Kubernetes journey, please consider joining our [sponsorship program](https://github.com/sponsors/derailed) and/or make some noise on social! [@kitesurfer](https://twitter.com/kitesurfer) + +On Slack? Please join us [K9slackers](https://join.slack.com/t/k9sers/shared_invite/enQtOTA5MDEyNzI5MTU0LWQ1ZGI3MzliYzZhZWEyNzYxYzA3NjE0YTk1YmFmNzViZjIyNzhkZGI0MmJjYzhlNjdlMGJhYzE2ZGU1NjkyNTM) + +--- + +## ♫ Sounds Behind The Release ♭ + +* [Bitches Brew - Miles Davis](https://www.youtube.com/watch?v=50fB5L1vmn8) +* [Sordid Affair - Röyksopp](https://www.youtube.com/watch?v=ECL5zO6ImsA) +* [Love Inc - Booka Shade](https://www.youtube.com/watch?v=sgLxTcok8kQ) +* [Twisted - Kaz James,Nick Morgan](https://www.youtube.com/watch?v=oOsYJ-Co8Y4) + +--- + +## A Word From Our Sponsors... + +To all the good folks below that opted to `pay it forward` and join our sponsorship program, I salute you!! + +* [Astraea](https://github.com/s22) +* [Arnaud Bienvenu](https://github.com/abienvenu) +* [Eric Caleb](https://github.com/iamcaleberic) +* [Sean Williams](https://github.com/SeanThomasWilliams) +* [Federico Ragona](https://github.com/fedragon) + +> Sponsorship cancellations since the last release: `7` ;( + +--- + +## Maintenance Release + +--- + +## Resolved Issues + +* [Issue #1968](https://github.com/derailed/k9s/issues/1968) Some skins are missing the definitions for the help menu +* [Issue #1967](https://github.com/derailed/k9s/issues/1967) Helm cve-2023-25165 +* [Issue #1964](https://github.com/derailed/k9s/issues/1964) logger.sinceSeconds config setting inconsistent with README +* [Issue #1955](https://github.com/derailed/k9s/issues/1955) K9s crashes with empty resources and/or verbs in RBAC +* [Issue #1954](https://github.com/derailed/k9s/issues/1954) Open very slow +* [Issue #1883](https://github.com/derailed/k9s/issues/1883) Fix force deletion +* [Issue #1788](https://github.com/derailed/k9s/issues/1788) Draining nodes cannot be forced +* [Issue #1150](https://github.com/derailed/k9s/issues/1150) Add a persistent popup for drain failures + +--- + +## Contributed PRs + +Please give `Big Thanks!` and `ATTA Girls/Boys!` to all the fine contributors for making K9s better for all of us!! + +* [PR #1969](https://github.com/derailed/k9s/pull/1969) fix: Add missing help menu to gruvbox-dark skin +* [PR #1966](https://github.com/derailed/k9s/pull/1966) fix: Show meaningful error message when kubectl exec fails +* [PR #1965](https://github.com/derailed/k9s/pull/1965) set default sinceSeconds to 300 +* [PR #1961](https://github.com/derailed/k9s/pull/1961) feat: Add sort by pod count on node view +* [PR #1960](https://github.com/derailed/k9s/pull/1960) [Misc] Add Nightfox-theme + +--- + + © 2022 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0) diff --git a/cmd/info.go b/cmd/info.go index e1f1bbd552..9828aab286 100644 --- a/cmd/info.go +++ b/cmd/info.go @@ -3,13 +3,14 @@ package cmd import ( "fmt" + "os" + "github.com/derailed/k9s/internal/color" "github.com/derailed/k9s/internal/config" "github.com/derailed/k9s/internal/ui" "github.com/rs/zerolog/log" "github.com/spf13/cobra" "gopkg.in/yaml.v2" - "os" ) func infoCmd() *cobra.Command { @@ -56,5 +57,9 @@ func getScreenDumpDirForInfo() string { log.Error().Err(err).Msgf("Unmarshal k9s config %v", err) return config.K9sDefaultScreenDumpDir } + if cfg.K9s == nil { + cfg.K9s = config.NewK9s() + } + return cfg.K9s.GetScreenDumpDir() } diff --git a/internal/dao/benchmark.go b/internal/dao/benchmark.go index 35f0bfdcbe..d0d1afe678 100644 --- a/internal/dao/benchmark.go +++ b/internal/dao/benchmark.go @@ -27,7 +27,7 @@ type Benchmark struct { } // Delete nukes a resource. -func (b *Benchmark) Delete(_ context.Context, path string, _ *metav1.DeletionPropagation, force bool) error { +func (b *Benchmark) Delete(_ context.Context, path string, _ *metav1.DeletionPropagation, _ Grace) error { return os.Remove(path) } diff --git a/internal/dao/generic.go b/internal/dao/generic.go index 7e8afc8c98..22e4eebefd 100644 --- a/internal/dao/generic.go +++ b/internal/dao/generic.go @@ -12,6 +12,19 @@ import ( "k8s.io/client-go/dynamic" ) +type Grace int64 + +const ( + // DefaultGrace uses delete default termination policy. + DefaultGrace Grace = -1 + + // ForceGrace sets delete grace-period to 0. + ForceGrace Grace = 0 + + // NowGrace set delete grace-period to 1, + NowGrace Grace = 1 +) + var _ Describer = (*Generic)(nil) // Generic represents a generic resource. @@ -88,7 +101,7 @@ func (g *Generic) ToYAML(path string, showManaged bool) (string, error) { } // Delete deletes a resource. -func (g *Generic) Delete(ctx context.Context, path string, propagation *metav1.DeletionPropagation, force bool) error { +func (g *Generic) Delete(ctx context.Context, path string, propagation *metav1.DeletionPropagation, grace Grace) error { ns, n := client.Namespaced(path) auth, err := g.Client().CanI(ns, g.gvr.String(), []string{client.DeleteVerb}) if err != nil { @@ -98,13 +111,13 @@ func (g *Generic) Delete(ctx context.Context, path string, propagation *metav1.D return fmt.Errorf("user is not authorized to delete %s", path) } - opts := metav1.DeleteOptions{ - PropagationPolicy: propagation, + var gracePeriod *int64 + if grace != DefaultGrace { + gracePeriod = (*int64)(&grace) } - - if force { - var defaultKillGrace int64 = 1 - opts.GracePeriodSeconds = &defaultKillGrace + opts := metav1.DeleteOptions{ + PropagationPolicy: propagation, + GracePeriodSeconds: gracePeriod, } dial, err := g.dynClient() diff --git a/internal/dao/helm.go b/internal/dao/helm.go index 322d2aa0e4..0c4ffd48c5 100644 --- a/internal/dao/helm.go +++ b/internal/dao/helm.go @@ -111,7 +111,7 @@ func (h *Helm) ToYAML(path string, showManaged bool) (string, error) { } // Delete uninstall a Helm. -func (h *Helm) Delete(_ context.Context, path string, _ *metav1.DeletionPropagation, force bool) error { +func (h *Helm) Delete(_ context.Context, path string, _ *metav1.DeletionPropagation, _ Grace) error { ns, n := client.Namespaced(path) cfg, err := h.EnsureHelmConfig(ns) if err != nil { diff --git a/internal/dao/node.go b/internal/dao/node.go index 8686d0c065..09540d865e 100644 --- a/internal/dao/node.go +++ b/internal/dao/node.go @@ -77,6 +77,7 @@ func (o DrainOptions) toDrainHelper(k kubernetes.Interface, w io.Writer) drain.H IgnoreAllDaemonSets: o.IgnoreAllDaemonSets, Out: w, ErrOut: w, + Force: o.Force, } } diff --git a/internal/dao/port_forward.go b/internal/dao/port_forward.go index c4f05837a7..8e7e4c5465 100644 --- a/internal/dao/port_forward.go +++ b/internal/dao/port_forward.go @@ -26,7 +26,7 @@ type PortForward struct { } // Delete deletes a portforward. -func (p *PortForward) Delete(_ context.Context, path string, _ *metav1.DeletionPropagation, _ bool) error { +func (p *PortForward) Delete(_ context.Context, path string, _ *metav1.DeletionPropagation, _ Grace) error { p.GetFactory().DeleteForwarder(path) return nil diff --git a/internal/dao/screen_dump.go b/internal/dao/screen_dump.go index c1c6092592..7ca9962684 100644 --- a/internal/dao/screen_dump.go +++ b/internal/dao/screen_dump.go @@ -22,7 +22,7 @@ type ScreenDump struct { } // Delete a ScreenDump. -func (d *ScreenDump) Delete(_ context.Context, path string, _ *metav1.DeletionPropagation, force bool) error { +func (d *ScreenDump) Delete(_ context.Context, path string, _ *metav1.DeletionPropagation, _ Grace) error { return os.Remove(path) } diff --git a/internal/dao/types.go b/internal/dao/types.go index e2650f41fc..aa1f49e27b 100644 --- a/internal/dao/types.go +++ b/internal/dao/types.go @@ -120,7 +120,7 @@ type Controller interface { // Nuker represents a resource deleter. type Nuker interface { // Delete removes a resource from the api server. - Delete(ctx context.Context, path string, propagation *metav1.DeletionPropagation, force bool) error + Delete(context.Context, string, *metav1.DeletionPropagation, Grace) error } // Switchable represents a switchable resource. diff --git a/internal/model/table.go b/internal/model/table.go index 799c385d6c..861fd1eb5b 100644 --- a/internal/model/table.go +++ b/internal/model/table.go @@ -111,7 +111,7 @@ func (t *Table) Get(ctx context.Context, path string) (runtime.Object, error) { } // Delete deletes a resource. -func (t *Table) Delete(ctx context.Context, path string, propagation *metav1.DeletionPropagation, force bool) error { +func (t *Table) Delete(ctx context.Context, path string, propagation *metav1.DeletionPropagation, grace dao.Grace) error { meta, err := getMeta(ctx, t.gvr) if err != nil { return err @@ -122,7 +122,7 @@ func (t *Table) Delete(ctx context.Context, path string, propagation *metav1.Del return fmt.Errorf("no nuker for %q", meta.DAO.GVR()) } - return nuker.Delete(ctx, path, propagation, force) + return nuker.Delete(ctx, path, propagation, grace) } // GetNamespace returns the model namespace. diff --git a/internal/render/policy.go b/internal/render/policy.go index 3670925056..9f3ff91941 100644 --- a/internal/render/policy.go +++ b/internal/render/policy.go @@ -74,6 +74,9 @@ func (Policy) Render(o interface{}, gvr string, r *Row) error { // Helpers... func cleanseResource(r string) string { + if r == "" { + return r + } if r[0] == '/' { return r } diff --git a/internal/ui/dialog/confirm.go b/internal/ui/dialog/confirm.go index e1e88d77c3..e7278e3441 100644 --- a/internal/ui/dialog/confirm.go +++ b/internal/ui/dialog/confirm.go @@ -6,11 +6,9 @@ import ( "github.com/derailed/tview" ) -const confirmKey = "confirm" +const dialogKey = "dialog" -type ( - confirmFunc func() -) +type confirmFunc func() // ShowConfirm pops a confirmation dialog. func ShowConfirm(styles config.Dialog, pages *ui.Pages, title, msg string, ack confirmFunc, cancel cancelFunc) { @@ -22,12 +20,12 @@ func ShowConfirm(styles config.Dialog, pages *ui.Pages, title, msg string, ack c SetLabelColor(styles.LabelFgColor.Color()). SetFieldTextColor(styles.FieldFgColor.Color()) f.AddButton("Cancel", func() { - dismissConfirm(pages) + dismiss(pages) cancel() }) f.AddButton("OK", func() { ack() - dismissConfirm(pages) + dismiss(pages) cancel() }) for i := 0; i < 2; i++ { @@ -43,13 +41,13 @@ func ShowConfirm(styles config.Dialog, pages *ui.Pages, title, msg string, ack c modal.SetText(msg) modal.SetTextColor(styles.FgColor.Color()) modal.SetDoneFunc(func(int, string) { - dismissConfirm(pages) + dismiss(pages) cancel() }) - pages.AddPage(confirmKey, modal, false, false) - pages.ShowPage(confirmKey) + pages.AddPage(dialogKey, modal, false, false) + pages.ShowPage(dialogKey) } -func dismissConfirm(pages *ui.Pages) { - pages.RemovePage(confirmKey) +func dismiss(pages *ui.Pages) { + pages.RemovePage(dialogKey) } diff --git a/internal/ui/dialog/confirm_test.go b/internal/ui/dialog/confirm_test.go index bda10a9db0..f5cd142985 100644 --- a/internal/ui/dialog/confirm_test.go +++ b/internal/ui/dialog/confirm_test.go @@ -22,9 +22,9 @@ func TestConfirmDialog(t *testing.T) { } ShowConfirm(config.Dialog{}, p, "Blee", "Yo", ackFunc, caFunc) - d := p.GetPrimitive(confirmKey).(*tview.ModalForm) + d := p.GetPrimitive(dialogKey).(*tview.ModalForm) assert.NotNil(t, d) - dismissConfirm(p) - assert.Nil(t, p.GetPrimitive(confirmKey)) + dismiss(p) + assert.Nil(t, p.GetPrimitive(dialogKey)) } diff --git a/internal/ui/dialog/delete.go b/internal/ui/dialog/delete.go index 0f8357c89f..bd1bb675b3 100644 --- a/internal/ui/dialog/delete.go +++ b/internal/ui/dialog/delete.go @@ -7,11 +7,15 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -const deleteKey = "delete" - -const noDeletePropagation = "None" +const ( + noDeletePropagation = "None" + defaultPropagationIdx = 0 +) -const defaultPropagationIdx = 0 +type ( + okFunc func(propagation *metav1.DeletionPropagation, force bool) + cancelFunc func() +) var propagationOptions []string = []string{ string(metav1.DeletePropagationBackground), @@ -20,11 +24,6 @@ var propagationOptions []string = []string{ noDeletePropagation, } -type ( - okFunc func(propagation *metav1.DeletionPropagation, force bool) - cancelFunc func() -) - // ShowDelete pops a resource deletion dialog. func ShowDelete(styles config.Dialog, pages *ui.Pages, msg string, ok okFunc, cancel cancelFunc) { propagation, force := "", false @@ -47,7 +46,7 @@ func ShowDelete(styles config.Dialog, pages *ui.Pages, msg string, ok okFunc, ca force = checked }) f.AddButton("Cancel", func() { - dismissDelete(pages) + dismiss(pages) cancel() }) f.AddButton("OK", func() { @@ -58,7 +57,7 @@ func ShowDelete(styles config.Dialog, pages *ui.Pages, msg string, ok okFunc, ca p := metav1.DeletionPropagation(propagation) ok(&p, force) } - dismissDelete(pages) + dismiss(pages) cancel() }) for i := 0; i < 2; i++ { @@ -74,13 +73,9 @@ func ShowDelete(styles config.Dialog, pages *ui.Pages, msg string, ok okFunc, ca confirm := tview.NewModalForm("", f) confirm.SetText(msg) confirm.SetDoneFunc(func(int, string) { - dismissDelete(pages) + dismiss(pages) cancel() }) - pages.AddPage(deleteKey, confirm, false, false) - pages.ShowPage(deleteKey) -} - -func dismissDelete(pages *ui.Pages) { - pages.RemovePage(deleteKey) + pages.AddPage(dialogKey, confirm, false, false) + pages.ShowPage(dialogKey) } diff --git a/internal/ui/dialog/delete_test.go b/internal/ui/dialog/delete_test.go index a81cdb00cf..a4c141668e 100644 --- a/internal/ui/dialog/delete_test.go +++ b/internal/ui/dialog/delete_test.go @@ -22,9 +22,9 @@ func TestDeleteDialog(t *testing.T) { } ShowDelete(config.Dialog{}, p, "Yo", okFunc, caFunc) - d := p.GetPrimitive(deleteKey).(*tview.ModalForm) + d := p.GetPrimitive(dialogKey).(*tview.ModalForm) assert.NotNil(t, d) - dismissDelete(p) - assert.Nil(t, p.GetPrimitive(deleteKey)) + dismiss(p) + assert.Nil(t, p.GetPrimitive(dialogKey)) } diff --git a/internal/ui/dialog/error.go b/internal/ui/dialog/error.go index b17a29aa56..f39e31fd36 100644 --- a/internal/ui/dialog/error.go +++ b/internal/ui/dialog/error.go @@ -10,7 +10,7 @@ import ( "github.com/derailed/tview" ) -// ShowConfirm pops a confirmation dialog. +// ShowError pops an error dialog. func ShowError(styles config.Dialog, pages *ui.Pages, msg string) { f := tview.NewForm() f.SetItemPadding(0) @@ -20,7 +20,7 @@ func ShowError(styles config.Dialog, pages *ui.Pages, msg string) { SetLabelColor(styles.LabelFgColor.Color()). SetFieldTextColor(tcell.ColorIndianRed) f.AddButton("Dismiss", func() { - dismissError(pages) + dismiss(pages) }) if b := f.GetButton(0); b != nil { b.SetBackgroundColorActivated(styles.ButtonFocusBgColor.Color()) @@ -31,14 +31,10 @@ func ShowError(styles config.Dialog, pages *ui.Pages, msg string) { modal.SetText(cowTalk(msg)) modal.SetTextColor(tcell.ColorOrangeRed) modal.SetDoneFunc(func(int, string) { - dismissError(pages) + dismiss(pages) }) - pages.AddPage(confirmKey, modal, false, false) - pages.ShowPage(confirmKey) -} - -func dismissError(pages *ui.Pages) { - pages.RemovePage(confirmKey) + pages.AddPage(dialogKey, modal, false, false) + pages.ShowPage(dialogKey) } func cowTalk(says string) string { diff --git a/internal/ui/dialog/error_test.go b/internal/ui/dialog/error_test.go new file mode 100644 index 0000000000..f882ac68da --- /dev/null +++ b/internal/ui/dialog/error_test.go @@ -0,0 +1,21 @@ +package dialog + +import ( + "testing" + + "github.com/derailed/k9s/internal/config" + "github.com/derailed/k9s/internal/ui" + "github.com/derailed/tview" + "github.com/stretchr/testify/assert" +) + +func TestErrorDialog(t *testing.T) { + p := ui.NewPages() + + ShowError(config.Dialog{}, p, "Yo") + + d := p.GetPrimitive(dialogKey).(*tview.ModalForm) + assert.NotNil(t, d) + dismiss(p) + assert.Nil(t, p.GetPrimitive(dialogKey)) +} diff --git a/internal/ui/table_test.go b/internal/ui/table_test.go index 0ba5e161e2..6567bb9a5a 100644 --- a/internal/ui/table_test.go +++ b/internal/ui/table_test.go @@ -8,6 +8,7 @@ import ( "github.com/derailed/k9s/internal" "github.com/derailed/k9s/internal/client" "github.com/derailed/k9s/internal/config" + "github.com/derailed/k9s/internal/dao" "github.com/derailed/k9s/internal/model" "github.com/derailed/k9s/internal/render" "github.com/derailed/k9s/internal/ui" @@ -80,7 +81,7 @@ func (t *mockModel) Get(ctx context.Context, path string) (runtime.Object, error return nil, nil } -func (t *mockModel) Delete(ctx context.Context, path string, p *metav1.DeletionPropagation, f bool) error { +func (t *mockModel) Delete(context.Context, string, *metav1.DeletionPropagation, dao.Grace) error { return nil } diff --git a/internal/ui/types.go b/internal/ui/types.go index c8f747ef5f..297f22b4f8 100644 --- a/internal/ui/types.go +++ b/internal/ui/types.go @@ -4,6 +4,7 @@ import ( "context" "time" + "github.com/derailed/k9s/internal/dao" "github.com/derailed/k9s/internal/model" "github.com/derailed/k9s/internal/render" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -78,5 +79,5 @@ type Tabular interface { RemoveListener(model.TableListener) // Delete a resource. - Delete(ctx context.Context, path string, propagation *metav1.DeletionPropagation, force bool) error + Delete(context.Context, string, *metav1.DeletionPropagation, dao.Grace) error } diff --git a/internal/view/alias_test.go b/internal/view/alias_test.go index 9b86d9bb0d..00f9168413 100644 --- a/internal/view/alias_test.go +++ b/internal/view/alias_test.go @@ -8,6 +8,7 @@ import ( "github.com/derailed/k9s/internal" "github.com/derailed/k9s/internal/client" "github.com/derailed/k9s/internal/config" + "github.com/derailed/k9s/internal/dao" "github.com/derailed/k9s/internal/model" "github.com/derailed/k9s/internal/render" "github.com/derailed/k9s/internal/ui" @@ -126,7 +127,7 @@ func (t *mockModel) Get(context.Context, string) (runtime.Object, error) { return nil, nil } -func (t *mockModel) Delete(context.Context, string, *metav1.DeletionPropagation, bool) error { +func (t *mockModel) Delete(context.Context, string, *metav1.DeletionPropagation, dao.Grace) error { return nil } diff --git a/internal/view/browser.go b/internal/view/browser.go index b4cdc548ec..3d833dd815 100644 --- a/internal/view/browser.go +++ b/internal/view/browser.go @@ -121,6 +121,7 @@ func (b *Browser) bindKeys(aa ui.KeyActions) { tcell.KeyEscape: ui.NewSharedKeyAction("Filter Reset", b.resetCmd, false), tcell.KeyEnter: ui.NewSharedKeyAction("Filter", b.filterCmd, false), tcell.KeyHelp: ui.NewSharedKeyAction("Help", b.helpCmd, false), + ui.KeyV: ui.NewSharedKeyAction("Zob", b.blahCmd, true), }) } @@ -350,6 +351,28 @@ func (b *Browser) deleteCmd(evt *tcell.EventKey) *tcell.EventKey { return nil } +func (b *Browser) blahCmd(evt *tcell.EventKey) *tcell.EventKey { + b.Stop() + defer b.Start() + { + v := NewDetails(b.app, "Results", "Blee", true) + if err := v.app.inject(v, false); err != nil { + v.app.Flash().Err(err) + } + + for i := 0; i < 10; i++ { + j := i + b.app.QueueUpdateDraw(func() { + log.Debug().Msgf("YO %d", j) + fmt.Fprintf(v.GetWriter(), "Yo %d\n", j) + time.Sleep(1 * time.Second) + }) + } + } + + return nil +} + func (b *Browser) describeCmd(evt *tcell.EventKey) *tcell.EventKey { path := b.GetSelectedItem() if path == "" { @@ -531,7 +554,7 @@ func (b *Browser) simpleDelete(selections []string, msg string) { b.app.Flash().Errf("Invalid nuker %T", b.accessor) continue } - if err := nuker.Delete(context.Background(), sel, nil, false); err != nil { + if err := nuker.Delete(context.Background(), sel, nil, dao.DefaultGrace); err != nil { b.app.Flash().Errf("Delete failed with `%s", err) } else { b.app.factory.DeleteForwarder(sel) @@ -551,7 +574,11 @@ func (b *Browser) resourceDelete(selections []string, msg string) { b.app.Flash().Infof("Delete resource %s %s", b.GVR(), selections[0]) } for _, sel := range selections { - if err := b.GetModel().Delete(b.defaultContext(), sel, propagation, force); err != nil { + grace := dao.DefaultGrace + if force { + grace = dao.ForceGrace + } + if err := b.GetModel().Delete(b.defaultContext(), sel, propagation, grace); err != nil { b.app.Flash().Errf("Delete failed with `%s", err) } else { b.app.factory.DeleteForwarder(sel) diff --git a/internal/view/details.go b/internal/view/details.go index 066b055891..d65485a2dc 100644 --- a/internal/view/details.go +++ b/internal/view/details.go @@ -3,6 +3,7 @@ package view import ( "context" "fmt" + "io" "strings" "github.com/derailed/k9s/internal/config" @@ -159,6 +160,10 @@ func (d *Details) Update(buff string) *Details { return d } +func (d *Details) GetWriter() io.Writer { + return d.text +} + // SetSubject updates the subject. func (d *Details) SetSubject(s string) { d.subject = s diff --git a/internal/view/help.go b/internal/view/help.go index bd04ebcb22..d9ce5085a8 100644 --- a/internal/view/help.go +++ b/internal/view/help.go @@ -281,7 +281,6 @@ func (h *Help) resetTitle() { func (h *Help) addSpacer(c int) { cell := tview.NewTableCell(render.Pad("", h.maxKey)) - cell.SetBackgroundColor(h.App().Styles.BgColor()) cell.SetExpansion(1) h.SetCell(0, c, cell) } diff --git a/internal/view/node.go b/internal/view/node.go index a025de51f0..9cce2783b7 100644 --- a/internal/view/node.go +++ b/internal/view/node.go @@ -1,10 +1,8 @@ package view import ( - "bytes" "context" "fmt" - "strings" "time" "github.com/derailed/k9s/internal/client" @@ -71,13 +69,11 @@ func (n *Node) drainCmd(evt *tcell.EventKey) *tcell.EventKey { return evt } - defaults := dao.DrainOptions{ - GracePeriodSeconds: -1, - Timeout: 5 * time.Second, - DeleteEmptyDirData: false, - IgnoreAllDaemonSets: false, + opts := dao.DrainOptions{ + GracePeriodSeconds: -1, + Timeout: 5 * time.Second, } - ShowDrain(n, path, defaults, drainNode) + ShowDrain(n, path, opts, drainNode) return nil } @@ -94,18 +90,20 @@ func drainNode(v ResourceViewer, path string, opts dao.DrainOptions) { return } - buff := bytes.NewBufferString("") - if err := m.Drain(path, opts, buff); err != nil { - v.App().Flash().Err(err) - return - } - lines := strings.Split(buff.String(), "\n") - for _, l := range lines { - if len(l) > 0 { - v.App().Flash().Info(l) + v.Stop() + defer v.Start() + { + d := NewDetails(v.App(), "Drain Progress", path, true) + if err := v.App().inject(d, false); err != nil { + v.App().Flash().Err(err) + } + + if err := m.Drain(path, opts, d.GetWriter()); err != nil { + v.App().Flash().Err(err) + return } + v.Refresh() } - v.Refresh() } func (n *Node) toggleCordonCmd(cordon bool) func(evt *tcell.EventKey) *tcell.EventKey { diff --git a/internal/view/pf.go b/internal/view/pf.go index 85b452c0ba..0d268089b1 100644 --- a/internal/view/pf.go +++ b/internal/view/pf.go @@ -160,7 +160,7 @@ func (p *PortForward) deleteCmd(evt *tcell.EventKey) *tcell.EventKey { for _, s := range selections { var pf dao.PortForward pf.Init(p.App().factory, client.NewGVR("portforwards")) - if err := pf.Delete(context.Background(), s, nil, true); err != nil { + if err := pf.Delete(context.Background(), s, nil, dao.DefaultGrace); err != nil { p.App().Flash().Err(err) return } diff --git a/internal/view/pod.go b/internal/view/pod.go index 58aa6667ba..531f16d83e 100644 --- a/internal/view/pod.go +++ b/internal/view/pod.go @@ -200,7 +200,7 @@ func (p *Pod) killCmd(evt *tcell.EventKey) *tcell.EventKey { } p.GetTable().ShowDeleted() for _, path := range selections { - if err := nuker.Delete(context.Background(), path, nil, true); err != nil { + if err := nuker.Delete(context.Background(), path, nil, dao.NowGrace); err != nil { p.App().Flash().Errf("Delete failed with %s", err) } else { p.App().factory.DeleteForwarder(path) diff --git a/internal/view/table_int_test.go b/internal/view/table_int_test.go index 6eb7b9b67c..cebdc3f5f0 100644 --- a/internal/view/table_int_test.go +++ b/internal/view/table_int_test.go @@ -10,6 +10,7 @@ import ( "github.com/derailed/k9s/internal" "github.com/derailed/k9s/internal/client" "github.com/derailed/k9s/internal/config" + "github.com/derailed/k9s/internal/dao" "github.com/derailed/k9s/internal/model" "github.com/derailed/k9s/internal/render" "github.com/derailed/k9s/internal/ui" @@ -140,7 +141,7 @@ func (t *mockTableModel) Get(context.Context, string) (runtime.Object, error) { return nil, nil } -func (t *mockTableModel) Delete(context.Context, string, *metav1.DeletionPropagation, bool) error { +func (t *mockTableModel) Delete(context.Context, string, *metav1.DeletionPropagation, dao.Grace) error { return nil } diff --git a/internal/view/xray.go b/internal/view/xray.go index ea86e377f7..87a05b38c5 100644 --- a/internal/view/xray.go +++ b/internal/view/xray.go @@ -672,7 +672,11 @@ func (x *Xray) resourceDelete(gvr client.GVR, spec *xray.NodeSpec, msg string) { x.app.Flash().Errf("Invalid nuker %T", accessor) return } - if err := nuker.Delete(context.Background(), spec.Path(), nil, true); err != nil { + grace := dao.DefaultGrace + if force { + grace = dao.ForceGrace + } + if err := nuker.Delete(context.Background(), spec.Path(), nil, grace); err != nil { x.app.Flash().Errf("Delete failed with `%s", err) } else { x.app.Flash().Infof("%s `%s deleted successfully", x.GVR(), spec.Path()) From dfdae882e10af1fa11569e3ddb00a0f36bc45a83 Mon Sep 17 00:00:00 2001 From: Richard Hull Date: Fri, 23 Sep 2022 18:38:21 +0100 Subject: [PATCH 13/14] [feat] Add toggle to allow log lines to be JSON colorized --- README.md | 2 ++ go.mod | 1 + go.sum | 2 ++ internal/config/config_test.go | 2 ++ internal/config/logger.go | 1 + internal/dao/log_item.go | 29 ++++++++++++++++++++++++----- internal/dao/log_item_test.go | 6 +++--- internal/dao/log_items.go | 26 +++++++++++++------------- internal/dao/log_items_test.go | 4 ++-- internal/dao/log_options.go | 1 + internal/model/log.go | 20 +++++++++++++------- internal/model/log_test.go | 6 +++--- internal/view/container.go | 1 + internal/view/dp.go | 1 + internal/view/log.go | 14 ++++++++++++++ internal/view/log_indicator.go | 19 +++++++++++++++++++ internal/view/log_indicator_test.go | 4 ++-- internal/view/log_int_test.go | 6 +++--- internal/view/log_test.go | 8 ++++---- internal/view/logs_extender.go | 1 + internal/view/pod.go | 1 + internal/view/sts.go | 1 + 22 files changed, 114 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index c4fdc8eeae..b439539b88 100644 --- a/README.md +++ b/README.md @@ -339,6 +339,8 @@ K9s uses aliases to navigate most K8s resources. textWrap: false # Toggles log line timestamp info. Default false showTime: false + # Toggles whether JSON log lines should be colorized. Default false + showJSON: false # Indicates the current kube context. Defaults to current context currentContext: minikube # Indicates the current kube cluster. Defaults to current context cluster diff --git a/go.mod b/go.mod index ff1548e1af..fd65e65cbc 100644 --- a/go.mod +++ b/go.mod @@ -122,6 +122,7 @@ require ( github.com/prometheus/common v0.37.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect github.com/rivo/uniseg v0.4.3 // indirect + github.com/rm-hull/colorjson v0.0.0-20220923220430-b50ee91dc6f6 // indirect github.com/rubenv/sql-migrate v1.2.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shopspring/decimal v1.2.0 // indirect diff --git a/go.sum b/go.sum index 9652caf1bd..2f99bc7efb 100644 --- a/go.sum +++ b/go.sum @@ -542,6 +542,8 @@ github.com/rakyll/hey v0.1.4/go.mod h1:nAOTOo+L52KB9SZq/M6J18kxjto4yVtXQDjU2HgjU github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rm-hull/colorjson v0.0.0-20220923220430-b50ee91dc6f6 h1:avrA8y9AJF9WtGipEvrM8I/7XoKcxEk30659rPHJlnM= +github.com/rm-hull/colorjson v0.0.0-20220923220430-b50ee91dc6f6/go.mod h1:tJTNxpJk1e15vd8WY5lsj9Tq5vjdnNz3YAbCwxYskBs= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 3821fd4589..b66daad14c 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -294,6 +294,7 @@ var expectedConfig = `k9s: fullScreenLogs: false textWrap: false showTime: false + showJSON: false currentContext: blee currentCluster: blee clusters: @@ -393,6 +394,7 @@ var resetConfig = `k9s: fullScreenLogs: false textWrap: false showTime: false + showJSON: false currentContext: blee currentCluster: blee clusters: diff --git a/internal/config/logger.go b/internal/config/logger.go index ba8c163887..a80f29e8d0 100644 --- a/internal/config/logger.go +++ b/internal/config/logger.go @@ -21,6 +21,7 @@ type Logger struct { FullScreenLogs bool `yaml:"fullScreenLogs"` TextWrap bool `yaml:"textWrap"` ShowTime bool `yaml:"showTime"` + ShowJSON bool `yaml:"showJSON"` } // NewLogger returns a new instance. diff --git a/internal/dao/log_item.go b/internal/dao/log_item.go index a66e1748d0..ddf7cc7cb9 100644 --- a/internal/dao/log_item.go +++ b/internal/dao/log_item.go @@ -2,6 +2,9 @@ package dao import ( "bytes" + "encoding/json" + + "github.com/rm-hull/colorjson" ) // LogChan represents a channel for logs. @@ -64,7 +67,7 @@ func (l *LogItem) Size() int { } // Render returns a log line as string. -func (l *LogItem) Render(paint string, showTime bool, bb *bytes.Buffer) { +func (l *LogItem) Render(paint string, showTime bool, showJson bool, bb *bytes.Buffer) { index := bytes.Index(l.Bytes, []byte{' '}) if showTime && index > 0 { bb.WriteString("[gray::b]") @@ -89,9 +92,25 @@ func (l *LogItem) Render(paint string, showTime bool, bb *bytes.Buffer) { bb.WriteString("[-::] ") } - if index > 0 { - bb.Write(l.Bytes[index+1:]) - } else { - bb.Write(l.Bytes) + bb.Write(colorizeJSON(l.Bytes[index+1:], showJson)) +} + +func colorizeJSON(text []byte, showJson bool) []byte { + if !showJson { + return text + } + var obj map[string]interface{} + err := json.Unmarshal(text, &obj) + if err != nil { + return text + } + f := colorjson.NewFormatter() + f.Indent = 0 + f.ObjectSeparator = false + + s, err := f.Marshal(obj) + if err != nil { + return text } + return append(s, '\n') } diff --git a/internal/dao/log_item_test.go b/internal/dao/log_item_test.go index 1eeacc548d..a8a81bea20 100644 --- a/internal/dao/log_item_test.go +++ b/internal/dao/log_item_test.go @@ -85,7 +85,7 @@ func TestLogItemRender(t *testing.T) { i.Pod, i.Container = n, u.opts.Container bb := bytes.NewBuffer(make([]byte, 0, i.Size())) - i.Render("yellow", u.opts.ShowTimestamp, bb) + i.Render("yellow", u.opts.ShowTimestamp, u.opts.ShowJSON, bb) assert.Equal(t, u.e, bb.String()) }) } @@ -100,7 +100,7 @@ func BenchmarkLogItemRender(b *testing.B) { b.ReportAllocs() for n := 0; n < b.N; n++ { bb := bytes.NewBuffer(make([]byte, 0, i.Size())) - i.Render("yellow", true, bb) + i.Render("yellow", true, false, bb) } } @@ -113,6 +113,6 @@ func BenchmarkLogItemRenderNoTS(b *testing.B) { b.ReportAllocs() for n := 0; n < b.N; n++ { bb := bytes.NewBuffer(make([]byte, 0, i.Size())) - i.Render("yellow", false, bb) + i.Render("yellow", false, false, bb) } } diff --git a/internal/dao/log_items.go b/internal/dao/log_items.go index 888c3db395..4b8590724d 100644 --- a/internal/dao/log_items.go +++ b/internal/dao/log_items.go @@ -101,7 +101,7 @@ func (l *LogItems) Add(ii ...*LogItem) { } // Lines returns a collection of log lines. -func (l *LogItems) Lines(index int, showTime bool, ll [][]byte) { +func (l *LogItems) Lines(index int, showTime bool, showJson bool, ll [][]byte) { l.mx.Lock() defer l.mx.Unlock() @@ -118,20 +118,20 @@ func (l *LogItems) Lines(index int, showTime bool, ll [][]byte) { colorIndex++ } bb := bytes.NewBuffer(make([]byte, 0, item.Size())) - item.Render(color, showTime, bb) + item.Render(color, showTime, showJson, bb) ll[i] = bb.Bytes() } } // StrLines returns a collection of log lines. -func (l *LogItems) StrLines(index int, showTime bool) []string { +func (l *LogItems) StrLines(index int, showTime bool, showJson bool) []string { l.mx.Lock() defer l.mx.Unlock() ll := make([]string, len(l.items[index:])) for i, item := range l.items[index:] { bb := bytes.NewBuffer(make([]byte, 0, item.Size())) - item.Render("white", showTime, bb) + item.Render("white", showTime, showJson, bb) ll[i] = bb.String() } @@ -139,7 +139,7 @@ func (l *LogItems) StrLines(index int, showTime bool) []string { } // Render returns logs as a collection of strings. -func (l *LogItems) Render(index int, showTime bool, ll [][]byte) { +func (l *LogItems) Render(index int, showTime bool, showJson bool, ll [][]byte) { var colorIndex int for i, item := range l.items[index:] { id := item.ID() @@ -153,7 +153,7 @@ func (l *LogItems) Render(index int, showTime bool, ll [][]byte) { colorIndex++ } bb := bytes.NewBuffer(make([]byte, 0, item.Size())) - item.Render(color, showTime, bb) + item.Render(color, showTime, showJson, bb) ll[i] = bb.Bytes() } } @@ -167,15 +167,15 @@ func (l *LogItems) DumpDebug(m string) { } // Filter filters out log items based on given filter. -func (l *LogItems) Filter(index int, q string, showTime bool) ([]int, [][]int, error) { +func (l *LogItems) Filter(index int, q string, showTime bool, showJson bool) ([]int, [][]int, error) { if q == "" { return nil, nil, nil } if IsFuzzySelector(q) { - mm, ii := l.fuzzyFilter(index, strings.TrimSpace(q[2:]), showTime) + mm, ii := l.fuzzyFilter(index, strings.TrimSpace(q[2:]), showTime, showJson) return mm, ii, nil } - matches, indices, err := l.filterLogs(index, q, showTime) + matches, indices, err := l.filterLogs(index, q, showTime, showJson) if err != nil { return nil, nil, err } @@ -183,10 +183,10 @@ func (l *LogItems) Filter(index int, q string, showTime bool) ([]int, [][]int, e return matches, indices, nil } -func (l *LogItems) fuzzyFilter(index int, q string, showTime bool) ([]int, [][]int) { +func (l *LogItems) fuzzyFilter(index int, q string, showTime bool, showJson bool) ([]int, [][]int) { q = strings.TrimSpace(q) matches, indices := make([]int, 0, len(l.items)), make([][]int, 0, 10) - mm := fuzzy.Find(q, l.StrLines(index, showTime)) + mm := fuzzy.Find(q, l.StrLines(index, showTime, showJson)) for _, m := range mm { matches = append(matches, m.Index) indices = append(indices, m.MatchedIndexes) @@ -195,7 +195,7 @@ func (l *LogItems) fuzzyFilter(index int, q string, showTime bool) ([]int, [][]i return matches, indices } -func (l *LogItems) filterLogs(index int, q string, showTime bool) ([]int, [][]int, error) { +func (l *LogItems) filterLogs(index int, q string, showTime bool, showJson bool) ([]int, [][]int, error) { var invert bool if IsInverseSelector(q) { invert = true @@ -207,7 +207,7 @@ func (l *LogItems) filterLogs(index int, q string, showTime bool) ([]int, [][]in } matches, indices := make([]int, 0, len(l.items)), make([][]int, 0, 10) ll := make([][]byte, len(l.items[index:])) - l.Lines(index, showTime, ll) + l.Lines(index, showTime, showJson, ll) for i, line := range ll { locs := rx.FindIndex(line) if locs != nil && invert { diff --git a/internal/dao/log_items_test.go b/internal/dao/log_items_test.go index e4e2742ea6..63839893b4 100644 --- a/internal/dao/log_items_test.go +++ b/internal/dao/log_items_test.go @@ -71,7 +71,7 @@ func TestLogItemsFilter(t *testing.T) { for _, i := range ii.Items() { i.Pod, i.Container = n, u.opts.Container } - res, _, err := ii.Filter(0, u.q, false) + res, _, err := ii.Filter(0, u.q, false, false) assert.Equal(t, u.err, err) if err == nil { assert.Equal(t, u.e, res) @@ -121,7 +121,7 @@ func TestLogItemsRender(t *testing.T) { ii.Items()[0].Pod, ii.Items()[0].Container = n, u.opts.Container t.Run(k, func(t *testing.T) { res := make([][]byte, 1) - ii.Render(0, u.opts.ShowTimestamp, res) + ii.Render(0, u.opts.ShowTimestamp, u.opts.ShowJSON, res) assert.Equal(t, u.e, string(res[0])) }) } diff --git a/internal/dao/log_options.go b/internal/dao/log_options.go index bd3fd03d6f..c83e9e5657 100644 --- a/internal/dao/log_options.go +++ b/internal/dao/log_options.go @@ -23,6 +23,7 @@ type LogOptions struct { SingleContainer bool MultiPods bool ShowTimestamp bool + ShowJSON bool AllContainers bool } diff --git a/internal/model/log.go b/internal/model/log.go index 52290a73cb..d0e7d88438 100644 --- a/internal/model/log.go +++ b/internal/model/log.go @@ -89,6 +89,12 @@ func (l *Log) ToggleShowTimestamp(b bool) { l.Refresh() } +// ToggleShowJSON toggles to colorize JSON logs. +func (l *Log) ToggleShowJSON(b bool) { + l.logOptions.ShowJSON = b + l.Refresh() +} + func (l *Log) Head(ctx context.Context) { l.mx.Lock() { @@ -146,7 +152,7 @@ func (l *Log) Clear() { func (l *Log) Refresh() { l.fireLogCleared() ll := make([][]byte, l.lines.Len()) - l.lines.Render(0, l.logOptions.ShowTimestamp, ll) + l.lines.Render(0, l.logOptions.ShowTimestamp, l.logOptions.ShowJSON, ll) l.fireLogChanged(ll) } @@ -181,7 +187,7 @@ func (l *Log) Set(lines *dao.LogItems) { l.fireLogCleared() ll := make([][]byte, l.lines.Len()) - l.lines.Render(0, l.logOptions.ShowTimestamp, ll) + l.lines.Render(0, l.logOptions.ShowTimestamp, l.logOptions.ShowJSON, ll) l.fireLogChanged(ll) } @@ -195,7 +201,7 @@ func (l *Log) ClearFilter() { l.fireLogCleared() ll := make([][]byte, l.lines.Len()) - l.lines.Render(0, l.logOptions.ShowTimestamp, ll) + l.lines.Render(0, l.logOptions.ShowTimestamp, l.logOptions.ShowJSON, ll) l.fireLogChanged(ll) } @@ -347,7 +353,7 @@ func (l *Log) applyFilter(index int, q string) ([][]byte, error) { if q == "" { return nil, nil } - matches, indices, err := l.lines.Filter(index, q, l.logOptions.ShowTimestamp) + matches, indices, err := l.lines.Filter(index, q, l.logOptions.ShowTimestamp, l.logOptions.ShowJSON) if err != nil { return nil, err } @@ -355,7 +361,7 @@ func (l *Log) applyFilter(index int, q string) ([][]byte, error) { // No filter! if matches == nil { ll := make([][]byte, l.lines.Len()) - l.lines.Render(index, l.logOptions.ShowTimestamp, ll) + l.lines.Render(index, l.logOptions.ShowTimestamp, l.logOptions.ShowJSON, ll) return ll, nil } // Blank filter @@ -364,7 +370,7 @@ func (l *Log) applyFilter(index int, q string) ([][]byte, error) { } filtered := make([][]byte, 0, len(matches)) ll := make([][]byte, l.lines.Len()) - l.lines.Lines(index, l.logOptions.ShowTimestamp, ll) + l.lines.Lines(index, l.logOptions.ShowTimestamp, l.logOptions.ShowJSON, ll) for i, idx := range matches { filtered = append(filtered, color.Highlight(ll[idx], indices[i], 209)) } @@ -375,7 +381,7 @@ func (l *Log) applyFilter(index int, q string) ([][]byte, error) { func (l *Log) fireLogBuffChanged(index int) { ll := make([][]byte, l.lines.Len()-index) if l.filter == "" { - l.lines.Render(index, l.logOptions.ShowTimestamp, ll) + l.lines.Render(index, l.logOptions.ShowTimestamp, l.logOptions.ShowJSON, ll) } else { ff, err := l.applyFilter(index, l.filter) if err != nil { diff --git a/internal/model/log_test.go b/internal/model/log_test.go index 09d00c6927..a0432fb0f0 100644 --- a/internal/model/log_test.go +++ b/internal/model/log_test.go @@ -154,7 +154,7 @@ func TestLogBasic(t *testing.T) { assert.Equal(t, 1, v.clearCalled) assert.Equal(t, 0, v.errCalled) ll := make([][]byte, data.Len()) - data.Lines(0, false, ll) + data.Lines(0, false, false, ll) assert.Equal(t, ll, v.data) } @@ -168,7 +168,7 @@ func TestLogAppend(t *testing.T) { items.Add(dao.NewLogItemFromString("blah blah")) m.Set(items) ll := make([][]byte, items.Len()) - items.Lines(0, false, ll) + items.Lines(0, false, false, ll) assert.Equal(t, ll, v.data) data := dao.NewLogItems() @@ -181,7 +181,7 @@ func TestLogAppend(t *testing.T) { } assert.Equal(t, 1, v.dataCalled) ll = make([][]byte, items.Len()) - items.Lines(0, false, ll) + items.Lines(0, false, false, ll) assert.Equal(t, ll, v.data) m.Notify() diff --git a/internal/view/container.go b/internal/view/container.go index 1ccad276c8..f285bd41b9 100644 --- a/internal/view/container.go +++ b/internal/view/container.go @@ -101,6 +101,7 @@ func (c *Container) logOptions(prev bool) (*dao.LogOptions, error) { SinceSeconds: cfg.SinceSeconds, SingleContainer: true, ShowTimestamp: cfg.ShowTime, + ShowJSON: cfg.ShowJSON, Previous: prev, } diff --git a/internal/view/dp.go b/internal/view/dp.go index 8bbfcfde46..2c135ef4a3 100644 --- a/internal/view/dp.go +++ b/internal/view/dp.go @@ -76,6 +76,7 @@ func (d *Deploy) logOptions(prev bool) (*dao.LogOptions, error) { SingleContainer: len(cc) == 1, AllContainers: allCos, ShowTimestamp: cfg.ShowTime, + ShowJSON: cfg.ShowJSON, Previous: prev, } if co == "" { diff --git a/internal/view/log.go b/internal/view/log.go index bf22e5b3d9..f47b61d8c3 100644 --- a/internal/view/log.go +++ b/internal/view/log.go @@ -94,6 +94,7 @@ func (l *Log) Init(ctx context.Context) (err error) { l.updateTitle() l.model.ToggleShowTimestamp(l.app.Config.K9s.Logger.ShowTime) + l.model.ToggleShowJSON((l.app.Config.K9s.Logger.ShowJSON)) return nil } @@ -248,6 +249,7 @@ func (l *Log) bindKeys() { ui.KeyM: ui.NewKeyAction("Mark", l.markCmd, true), ui.KeyS: ui.NewKeyAction("Toggle AutoScroll", l.toggleAutoScrollCmd, true), ui.KeyF: ui.NewKeyAction("Toggle FullScreen", l.toggleFullScreenCmd, true), + ui.KeyJ: ui.NewKeyAction("Toggle JSON", l.toggleJSONCmd, true), ui.KeyT: ui.NewKeyAction("Toggle Timestamp", l.toggleTimestampCmd, true), ui.KeyW: ui.NewKeyAction("Toggle Wrap", l.toggleTextWrapCmd, true), tcell.KeyCtrlS: ui.NewKeyAction("Save", l.SaveCmd, true), @@ -345,6 +347,7 @@ func (l *Log) Flush(lines [][]byte) { if l.cancelUpdates { break } + _, _ = l.ansiWriter.Write(lines[i]) } if l.follow { @@ -508,6 +511,17 @@ func (l *Log) toggleFullScreen() { } } +func (l *Log) toggleJSONCmd(evt *tcell.EventKey) *tcell.EventKey { + if l.app.InCmdMode() { + return evt + } + l.indicator.ToggleJSON() + l.model.ToggleShowJSON(l.indicator.showJson) + l.indicator.Refresh() + + return nil +} + func (l *Log) isContainerLogView() bool { return l.model.HasDefaultContainer() } diff --git a/internal/view/log_indicator.go b/internal/view/log_indicator.go index ff360b589f..c36ac14c92 100644 --- a/internal/view/log_indicator.go +++ b/internal/view/log_indicator.go @@ -19,6 +19,7 @@ type LogIndicator struct { fullScreen bool textWrap bool showTime bool + showJson bool allContainers bool shouldDisplayAllContainers bool } @@ -33,6 +34,7 @@ func NewLogIndicator(cfg *config.Config, styles *config.Styles, allContainers bo fullScreen: cfg.K9s.Logger.FullScreenLogs, textWrap: cfg.K9s.Logger.TextWrap, showTime: cfg.K9s.Logger.ShowTime, + showJson: cfg.K9s.Logger.ShowJSON, shouldDisplayAllContainers: allContainers, } l.StylesChanged(styles) @@ -69,6 +71,11 @@ func (l *LogIndicator) FullScreen() bool { return l.fullScreen } +// Json reports the whether the logs are JSON colorized. +func (l *LogIndicator) Json() bool { + return l.showJson +} + // ToggleTimestamp toggles the current timestamp mode. func (l *LogIndicator) ToggleTimestamp() { l.showTime = !l.showTime @@ -80,6 +87,12 @@ func (l *LogIndicator) ToggleFullScreen() { l.Refresh() } +// ToggleJSON toggles the whether JSON logging is colorized. +func (l *LogIndicator) ToggleJSON() { + l.showJson = !l.showJson + l.Refresh() +} + // ToggleTextWrap toggles the wrap mode. func (l *LogIndicator) ToggleTextWrap() { l.textWrap = !l.textWrap @@ -131,6 +144,12 @@ func (l *LogIndicator) Refresh() { l.indicator = append(l.indicator, "[::b]FullScreen:[gray::d]Off[-::]"+spacer...) } + if l.Json() { + l.indicator = append(l.indicator, "[::b]JSON:[limegreen::b]On[-::] "+spacer...) + } else { + l.indicator = append(l.indicator, "[::b]JSON:[gray::d]Off[-::]"+spacer...) + } + if l.Timestamp() { l.indicator = append(l.indicator, "[::b]Timestamps:[limegreen::b]On[-::] "+spacer...) } else { diff --git a/internal/view/log_indicator_test.go b/internal/view/log_indicator_test.go index 2432a938ca..48db3eb156 100644 --- a/internal/view/log_indicator_test.go +++ b/internal/view/log_indicator_test.go @@ -15,10 +15,10 @@ func TestLogIndicatorRefresh(t *testing.T) { e string }{ "all-containers": { - view.NewLogIndicator(config.NewConfig(nil), defaults, true), "[::b]AllContainers:[gray::d]Off[-::] [::b]Autoscroll:[limegreen::b]On[-::] [::b]FullScreen:[gray::d]Off[-::] [::b]Timestamps:[gray::d]Off[-::] [::b]Wrap:[gray::d]Off[-::]\n", + view.NewLogIndicator(config.NewConfig(nil), defaults, true), "[::b]AllContainers:[gray::d]Off[-::] [::b]Autoscroll:[limegreen::b]On[-::] [::b]FullScreen:[gray::d]Off[-::] [::b]JSON:[gray::d]Off[-::] [::b]Timestamps:[gray::d]Off[-::] [::b]Wrap:[gray::d]Off[-::]\n", }, "plain": { - view.NewLogIndicator(config.NewConfig(nil), defaults, false), "[::b]Autoscroll:[limegreen::b]On[-::] [::b]FullScreen:[gray::d]Off[-::] [::b]Timestamps:[gray::d]Off[-::] [::b]Wrap:[gray::d]Off[-::]\n", + view.NewLogIndicator(config.NewConfig(nil), defaults, false), "[::b]Autoscroll:[limegreen::b]On[-::] [::b]FullScreen:[gray::d]Off[-::] [::b]JSON:[gray::d]Off[-::] [::b]Timestamps:[gray::d]Off[-::] [::b]Wrap:[gray::d]Off[-::]\n", }, } diff --git a/internal/view/log_int_test.go b/internal/view/log_int_test.go index ac0a101afe..6f51195765 100644 --- a/internal/view/log_int_test.go +++ b/internal/view/log_int_test.go @@ -23,10 +23,10 @@ func TestLogAutoScroll(t *testing.T) { v.GetModel().Set(ii) v.GetModel().Notify() - assert.Equal(t, 16, len(v.Hints())) + assert.Equal(t, 17, len(v.Hints())) v.toggleAutoScrollCmd(nil) - assert.Equal(t, "Autoscroll:Off FullScreen:Off Timestamps:Off Wrap:Off", v.Indicator().GetText(true)) + assert.Equal(t, "Autoscroll:Off FullScreen:Off JSON:Off Timestamps:Off Wrap:Off", v.Indicator().GetText(true)) } func TestLogViewNav(t *testing.T) { @@ -84,7 +84,7 @@ func TestLogTimestamp(t *testing.T) { l.SendKeys(ui.KeyT) l.Logs().Clear() ll := make([][]byte, ii.Len()) - ii.Lines(0, true, ll) + ii.Lines(0, true, false, ll) l.Flush(ll) assert.Equal(t, fmt.Sprintf("%-30s %s", "ttt", "fred/blee c1 Testing 1, 2, 3\n"), l.Logs().GetText(true)) diff --git a/internal/view/log_test.go b/internal/view/log_test.go index 945aae3eb5..d5c4cc8e49 100644 --- a/internal/view/log_test.go +++ b/internal/view/log_test.go @@ -27,7 +27,7 @@ func TestLog(t *testing.T) { ii := dao.NewLogItems() ii.Add(dao.NewLogItemFromString("blee\n"), dao.NewLogItemFromString("bozo\n")) ll := make([][]byte, ii.Len()) - ii.Lines(0, false, ll) + ii.Lines(0, false, false, ll) v.Flush(ll) assert.Equal(t, "Waiting for logs...\nblee\nbozo\n", v.Logs().GetText(true)) @@ -47,7 +47,7 @@ func TestLogFlush(t *testing.T) { dao.NewLogItemFromString("\033[0;32mBozo\n"), ) ll := make([][]byte, items.Len()) - items.Lines(0, false, ll) + items.Lines(0, false, false, ll) v.Flush(ll) assert.Equal(t, "[orange::d]Waiting for logs...\n[black::]blee\n[green::]Bozo\n\n", v.Logs().GetText(false)) @@ -68,7 +68,7 @@ func BenchmarkLogFlush(b *testing.B) { dao.NewLogItemFromString("\033[0;101mBozo\n"), ) ll := make([][]byte, items.Len()) - items.Lines(0, false, ll) + items.Lines(0, false, false, ll) b.ReportAllocs() b.ResetTimer() @@ -103,7 +103,7 @@ func TestLogViewSave(t *testing.T) { ii := dao.NewLogItems() ii.Add(dao.NewLogItemFromString("blee"), dao.NewLogItemFromString("bozo")) ll := make([][]byte, ii.Len()) - ii.Lines(0, false, ll) + ii.Lines(0, false, false, ll) v.Flush(ll) dir := filepath.Join(app.Config.K9s.GetScreenDumpDir(), app.Config.K9s.CurrentCluster) diff --git a/internal/view/logs_extender.go b/internal/view/logs_extender.go index d390c3654d..b31b80f426 100644 --- a/internal/view/logs_extender.go +++ b/internal/view/logs_extender.go @@ -81,6 +81,7 @@ func (l *LogsExtender) buildLogOpts(path, co string, prevLogs bool) *dao.LogOpti Lines: int64(cfg.TailCount), Previous: prevLogs, ShowTimestamp: cfg.ShowTime, + ShowJSON: cfg.ShowJSON, } if opts.Container == "" { opts.AllContainers = true diff --git a/internal/view/pod.go b/internal/view/pod.go index 531f16d83e..120dd56f65 100644 --- a/internal/view/pod.go +++ b/internal/view/pod.go @@ -102,6 +102,7 @@ func (p *Pod) logOptions(prev bool) (*dao.LogOptions, error) { SinceSeconds: cfg.SinceSeconds, SingleContainer: len(cc) == 1, ShowTimestamp: cfg.ShowTime, + ShowJSON: cfg.ShowJSON, Previous: prev, } if c, ok := dao.GetDefaultLogContainer(pod.ObjectMeta, pod.Spec); ok { diff --git a/internal/view/sts.go b/internal/view/sts.go index 5ddc4ef3e6..2f779b01bb 100644 --- a/internal/view/sts.go +++ b/internal/view/sts.go @@ -65,6 +65,7 @@ func (s *StatefulSet) logOptions(prev bool) (*dao.LogOptions, error) { SinceSeconds: cfg.SinceSeconds, AllContainers: allCos, ShowTimestamp: cfg.ShowTime, + ShowJSON: cfg.ShowJSON, Previous: prev, } if co == "" { From e70387e6334c2f31f38e2194a814b89a8e616d0d Mon Sep 17 00:00:00 2001 From: Richard Hull Date: Sat, 11 Feb 2023 17:34:26 +0000 Subject: [PATCH 14/14] Toggle JSON with Ctrl-J --- internal/view/log.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/view/log.go b/internal/view/log.go index f47b61d8c3..c70c2afdf9 100644 --- a/internal/view/log.go +++ b/internal/view/log.go @@ -249,7 +249,7 @@ func (l *Log) bindKeys() { ui.KeyM: ui.NewKeyAction("Mark", l.markCmd, true), ui.KeyS: ui.NewKeyAction("Toggle AutoScroll", l.toggleAutoScrollCmd, true), ui.KeyF: ui.NewKeyAction("Toggle FullScreen", l.toggleFullScreenCmd, true), - ui.KeyJ: ui.NewKeyAction("Toggle JSON", l.toggleJSONCmd, true), + tcell.KeyCtrlJ: ui.NewKeyAction("Toggle JSON", l.toggleJSONCmd, true), ui.KeyT: ui.NewKeyAction("Toggle Timestamp", l.toggleTimestampCmd, true), ui.KeyW: ui.NewKeyAction("Toggle Wrap", l.toggleTextWrapCmd, true), tcell.KeyCtrlS: ui.NewKeyAction("Save", l.SaveCmd, true),