K9s/rel v0.28.0 (#2274)
* check for plausible overflow when seting up env * Various fixes and clean up * Introduce File transfer command - Add ability to upload/download files from/to pods * release v0.28.0mine
parent
f4d2ca621a
commit
d19c792feb
2
Makefile
2
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.4
|
||||
VERSION ?= v0.28.0
|
||||
IMG_NAME := derailed/k9s
|
||||
IMAGE := ${IMG_NAME}:${VERSION}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,113 @@
|
|||
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/k9s.png" align="center" width="800" height="auto"/>
|
||||
|
||||
# Release v0.28.0
|
||||
|
||||
## 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 ♭
|
||||
|
||||
* [Moonlight Invasions - TribalNeed](https://www.youtube.com/watch?v=mJBnMSNIJL4&list=RDmJBnMSNIJL4&start_radio=1)
|
||||
* [Teardrops - Neil Frances](https://www.youtube.com/watch?v=823_KoZr4mo)
|
||||
* [Memory - Øystein Sevåg](https://www.youtube.com/watch?v=GKEM6lgkogY)
|
||||
* [Tell me straight - Rolling Stones (Generated by KeithGPT 🐭)](https://www.youtube.com/watch?v=YxcxLi-Ld3E)
|
||||
|
||||
---
|
||||
|
||||
## 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!!
|
||||
|
||||
* [Hyeon Woo Jo](https://github.com/dokdo2013)
|
||||
* [Artsiom Kaval](https://github.com/lezeroq)
|
||||
* [Grant Linville](https://github.com/g-linville)
|
||||
* [Andrew Brown](https://github.com/andrew-werdna)
|
||||
* [Patrik Votoček](https://github.com/Vrtak-CZ)
|
||||
* [Erik Hebisch](https://github.com/flegelleicht)
|
||||
* [Juliet Boyd](https://github.com/julietrb1)
|
||||
* [Chris Vertonghen](https://github.com/chrisv)
|
||||
* [Acsone](https://github.com/acsone)
|
||||
* [Alex Viscreanu](https://github.com/aexvir)
|
||||
* [Joey Guerra](https://github.com/joeyguerra)
|
||||
* [Kijana Woodard](https://github.com/kijanawoodard)
|
||||
* [Tom Saleeba](https://github.com/tomsaleeba)
|
||||
|
||||
> Sponsorship cancellations since the last release: `11` ;(
|
||||
|
||||
---
|
||||
|
||||
## Feature Release
|
||||
|
||||
### File Transfers in Da House!
|
||||
|
||||
Added ability to exchange files from your local machine to a pod or from a pod to your local machine. The pod view now surfaces a new command `t` to initiate the download/upload file transfers.
|
||||
|
||||
---
|
||||
|
||||
## Resolved Issues
|
||||
|
||||
* [Issue #2249](https://github.com/derailed/k9s/issues/2249) Sort on the capacity column should consider Gi and Mb also
|
||||
* [Issue #2225](https://github.com/derailed/k9s/issues/2225) View logs of all pods of a given deployment
|
||||
* [Issue #2195](https://github.com/derailed/k9s/issues/2195) Some pod logs are not displayed. But I can display it when I use the command
|
||||
|
||||
* [Issue #2194](https://github.com/derailed/k9s/issues/2194) 0.27.4 broke custom sort orders via views.yml
|
||||
* [Issue #2185](https://github.com/derailed/k9s/issues/2185) No binaries for Linux_x86_64
|
||||
* [Issue #2169](https://github.com/derailed/k9s/issues/2169) Add namespace name in ServiceAccount view with RoleBinding
|
||||
* [Issue #2152](https://github.com/derailed/k9s/issues/2152) Latest opened namespace not being saved between k9s sessions
|
||||
* [Issue #2131](https://github.com/derailed/k9s/issues/2131) deployments are not showing up, whereas kubectl gives a list
|
||||
* [Issue #2130](https://github.com/derailed/k9s/issues/2130) Pending pods show 0/0 Ready instead of 0/x Ready
|
||||
* [Issue #2128](https://github.com/derailed/k9s/issues/2128) k9s command not found after snap install
|
||||
* [Issue #2121](https://github.com/derailed/k9s/issues/2121) colors for crds
|
||||
* [Issue #2120](https://github.com/derailed/k9s/issues/2120) kustomize deletion not working as expected
|
||||
* [Issue #2106](https://github.com/derailed/k9s/issues/2106) k9s delete behaves differently with kubectl
|
||||
* [Issue #2085](https://github.com/derailed/k9s/issues/2085) When specifying the context command via the -c flag, selecting a cluster always returns to the context view
|
||||
* [Issue #658](https://github.com/derailed/k9s/issues/658) Feature request: Easy way to copy/download files from a pod/pv to your local PC
|
||||
|
||||
---
|
||||
|
||||
## Contributed PRs
|
||||
|
||||
Please give `Big Thanks!` and `ATTA Girls/Boys!` to all the fine contributors for making K9s better for all of us!!
|
||||
|
||||
* [PR #2258](https://github.com/derailed/k9s/pull/2258) fix fsnotify watcher not fully working
|
||||
* [PR #2253](https://github.com/derailed/k9s/pull/2253) fix manual sorting not working when sortColumn is configured
|
||||
* [PR #2252](https://github.com/derailed/k9s/pull/2252) consider units when sorting capacity of pv and pvc
|
||||
* [PR #2243](https://github.com/derailed/k9s/pull/2243) fix(typo): pdb header typo
|
||||
* [PR #2239](https://github.com/derailed/k9s/pull/2239) fix: honor defaults from drain dialog in request
|
||||
* [PR #2235](https://github.com/derailed/k9s/pull/2235) docs: add plugin.yml JSON schema
|
||||
* [PR #2229](https://github.com/derailed/k9s/pull/2229) fix(log): clear bold log format after timestamp
|
||||
* [PR #2188](https://github.com/derailed/k9s/pull/2188) Alias qa to quit
|
||||
* [PR #2180](https://github.com/derailed/k9s/pull/2180) feat: Added support for arm in dockerfile
|
||||
* [PR #2179](https://github.com/derailed/k9s/pull/2179) Focus command bar if active on startup
|
||||
* [PR #2170](https://github.com/derailed/k9s/pull/2170) Add namespace for rolebinding on a clusterrole
|
||||
* [PR #2161](https://github.com/derailed/k9s/pull/2161) Only apply keyConv to mnemonic in menus
|
||||
* [PR #2158](https://github.com/derailed/k9s/pull/2158) Show the default container as the first entry
|
||||
* [PR #2153](https://github.com/derailed/k9s/pull/2153) Changed checksums extension to checksums.sha256
|
||||
* [PR #2158](https://github.com/derailed/k9s/pull/2158) Show the default container as the first entry
|
||||
* [PR #2151](https://github.com/derailed/k9s/pull/2151) chore: pkg imported more than once
|
||||
* [PR #2147](https://github.com/derailed/k9s/pull/2147) feat: plugin for adding an ephemeral debug container
|
||||
* [PR #2141](https://github.com/derailed/k9s/pull/2141) Update plugin flux.yml with shortcuts for helm repo and oci repos
|
||||
* [PR #2137](https://github.com/derailed/k9s/pull/2137) Correctly display the numbers in the Ready column of the pods view
|
||||
* [PR #2136](https://github.com/derailed/k9s/pull/2136) Prompt window uses border styles
|
||||
* [PR #2134](https://github.com/derailed/k9s/pull/2134) Remove unsupported key binding on users view
|
||||
* [PR #2124](https://github.com/derailed/k9s/pull/2124) fix: add correct flags when deleting resources from Dir
|
||||
* [PR #2119](https://github.com/derailed/k9s/pull/2119) feat: add indicator to title if toast is toggled
|
||||
* [PR #2117](https://github.com/derailed/k9s/pull/2117) Add instruction how to install k9s through winget
|
||||
* [PR #2112](https://github.com/derailed/k9s/pull/2112) Fix for styles
|
||||
* [PR #2105](https://github.com/derailed/k9s/pull/2105) Fix the wrong/redundant icon in the prompt bar
|
||||
* [PR #2103](https://github.com/derailed/k9s/pull/2103) Update carvel.yml to include contexts
|
||||
* [PR #2096](https://github.com/derailed/k9s/pull/2096) fix: (config) only respect the --command flag once
|
||||
* [PR #2091](https://github.com/derailed/k9s/pull/2091) Add get-all plugin specific for namespace view
|
||||
* [PR #2089](https://github.com/derailed/k9s/pull/2089) Resources are rendered using skin.yaml colors
|
||||
* [PR #2082](https://github.com/derailed/k9s/pull/2082) Fix typo introduced in #2045
|
||||
|
||||
---
|
||||
|
||||
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/imhotep_logo.png" width="32" height="auto"/> © 2023 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
14
go.mod
14
go.mod
|
|
@ -1,6 +1,6 @@
|
|||
module github.com/derailed/k9s
|
||||
|
||||
go 1.20
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/adrg/xdg v0.4.0
|
||||
|
|
@ -25,12 +25,12 @@ require (
|
|||
gopkg.in/yaml.v2 v2.4.0
|
||||
helm.sh/helm/v3 v3.13.1
|
||||
k8s.io/api v0.28.3
|
||||
k8s.io/apiextensions-apiserver v0.28.2
|
||||
k8s.io/apiextensions-apiserver v0.28.3
|
||||
k8s.io/apimachinery v0.28.3
|
||||
k8s.io/cli-runtime v0.28.2
|
||||
k8s.io/cli-runtime v0.28.3
|
||||
k8s.io/client-go v0.28.3
|
||||
k8s.io/klog/v2 v2.110.1
|
||||
k8s.io/kubectl v0.28.2
|
||||
k8s.io/klog/v2 v2.100.1
|
||||
k8s.io/kubectl v0.28.3
|
||||
k8s.io/metrics v0.28.3
|
||||
sigs.k8s.io/yaml v1.3.0
|
||||
)
|
||||
|
|
@ -152,8 +152,8 @@ require (
|
|||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/apiserver v0.28.2 // indirect
|
||||
k8s.io/component-base v0.28.2 // indirect
|
||||
k8s.io/apiserver v0.28.3 // indirect
|
||||
k8s.io/component-base v0.28.3 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
|
||||
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect
|
||||
oras.land/oras-go v1.2.4 // indirect
|
||||
|
|
|
|||
71
go.sum
71
go.sum
|
|
@ -7,6 +7,7 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
|||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
||||
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
|
|
@ -19,14 +20,17 @@ github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBa
|
|||
github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM=
|
||||
github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10=
|
||||
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||
github.com/Microsoft/hcsshim v0.11.0 h1:7EFNIY4igHEXUdj1zXgAyU3fLc7QfOKHbkldRVTBdiM=
|
||||
github.com/Microsoft/hcsshim v0.11.0/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM=
|
||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs=
|
||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
|
||||
github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls=
|
||||
github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY=
|
||||
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
|
||||
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
||||
|
|
@ -38,9 +42,13 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce
|
|||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70=
|
||||
github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
|
||||
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd h1:rFt+Y/IK1aEZkEHchZRSq9OQbsSzIT/OrI8YFFmRIng=
|
||||
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
|
||||
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ=
|
||||
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
|
||||
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o=
|
||||
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
|
|
@ -53,13 +61,16 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
|
|||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
|
||||
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
|
||||
github.com/containerd/containerd v1.7.6 h1:oNAVsnhPoy4BTPQivLgTzI9Oleml9l/+eYIDYXRCYo8=
|
||||
github.com/containerd/containerd v1.7.6/go.mod h1:SY6lrkkuJT40BVNO37tlYTSnKJnP5AXBc0fhx0q+TJ4=
|
||||
github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM=
|
||||
github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
||||
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
|
@ -72,6 +83,7 @@ github.com/derailed/tcell/v2 v2.3.1-rc.3/go.mod h1:nf68BEL8fjmXQHJT3xZjoZFs2uXOz
|
|||
github.com/derailed/tview v0.8.1 h1:hvNR3LLrWEuaQbPYfBnRn7bYkxCP26K6nX9J+MGlhyw=
|
||||
github.com/derailed/tview v0.8.1/go.mod h1:q+odnnhO6QDPpBT+0dqaWj+X+uoJ6MJehXj9shgP+Cw=
|
||||
github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2 h1:aBfCb7iqHmDEIp6fBvC/hQUddQfg+3qdYjwzaiP9Hnc=
|
||||
github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2/go.mod h1:WHNsWjnIn2V1LYOrME7e8KxSeKunYHsxEm4am0BUtcI=
|
||||
github.com/docker/cli v24.0.6+incompatible h1:fF+XCQCgJjjQNIMjzaSmiKJSCcfcXb3TWTcc7GAneOY=
|
||||
github.com/docker/cli v24.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
|
||||
|
|
@ -83,11 +95,13 @@ github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNk
|
|||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
||||
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
|
||||
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4=
|
||||
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
|
||||
github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ=
|
||||
github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
|
|
@ -101,8 +115,11 @@ github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwo
|
|||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
|
||||
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/foxcpp/go-mockdns v1.0.0 h1:7jBqxd3WDWwi/6WhDvacvH1XsN3rOLXyHM1uhvIx6FI=
|
||||
github.com/foxcpp/go-mockdns v1.0.0/go.mod h1:lgRN6+KxQBawyIghpnl5CezHFGS9VLzvtVlwxvzXTQ4=
|
||||
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
||||
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
|
||||
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=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
|
|
@ -136,9 +153,13 @@ github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB
|
|||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU=
|
||||
github.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs=
|
||||
github.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0=
|
||||
github.com/gobuffalo/packd v1.0.1/go.mod h1:PP2POP3p3RXGz7Jh6eYEf93S7vA2za6xM7QT85L4+VY=
|
||||
github.com/gobuffalo/packr/v2 v2.8.3 h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XEWlY=
|
||||
github.com/gobuffalo/packr/v2 v2.8.3/go.mod h1:0SahksCVcx4IMnigTjiFuyldmTrdTctXsOdiU5KwbKc=
|
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
|
|
@ -147,6 +168,7 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
|||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
|
|
@ -162,6 +184,7 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
|
|||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k=
|
||||
github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
|
||||
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
||||
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
||||
|
|
@ -179,12 +202,14 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
|
|||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
|
||||
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
|
|
@ -198,6 +223,7 @@ github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv
|
|||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
|
||||
|
|
@ -221,6 +247,7 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
|
|||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw=
|
||||
github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4=
|
||||
|
|
@ -229,6 +256,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv
|
|||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
|
|
@ -247,11 +275,15 @@ github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9
|
|||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
|
||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI=
|
||||
github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc=
|
||||
github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY=
|
||||
github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI=
|
||||
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.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
|
|
@ -262,10 +294,12 @@ github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWV
|
|||
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
|
||||
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/miekg/dns v1.1.25 h1:dFwPR6SfLtrSwgDcIq2bcU/gVutB4sNApq2HBdqcakg=
|
||||
github.com/miekg/dns v1.1.25/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
|
||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||
|
|
@ -279,6 +313,7 @@ github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQ
|
|||
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
|
||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
||||
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
|
||||
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
|
|
@ -303,6 +338,7 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108
|
|||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/ginkgo/v2 v2.9.4 h1:xR7vG4IXt5RWx6FfIjyAtsoMAtnc3C/rFXBBd2AjZwE=
|
||||
github.com/onsi/ginkgo/v2 v2.9.4/go.mod h1:gCQYp2Q+kSoIj7ykSVb9nskRSsR6PUj4AiLywzIhbKM=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
|
||||
|
|
@ -316,12 +352,14 @@ github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR
|
|||
github.com/petergtz/pegomock v2.9.0+incompatible h1:BKfb5XfkJfehe5T+O1xD4Zm26Sb9dnRj7tHxLYwUPiI=
|
||||
github.com/petergtz/pegomock v2.9.0+incompatible/go.mod h1:nuBLWZpVyv/fLo56qTwt/AUau7jgouO1h7bEvZCq82o=
|
||||
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
|
||||
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY=
|
||||
github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
|
||||
|
|
@ -347,6 +385,7 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
|
|||
github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw=
|
||||
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A=
|
||||
github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||
|
|
@ -357,6 +396,7 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
|
|||
github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI=
|
||||
github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
|
||||
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
|
|
@ -397,9 +437,13 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI=
|
||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
||||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE=
|
||||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
||||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1:ERexzlUfuTvpE74urLSbIQW0Z/6hF9t8U4NsJLaioAY=
|
||||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM=
|
||||
go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU=
|
||||
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M=
|
||||
|
|
@ -422,6 +466,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
|
||||
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
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=
|
||||
|
|
@ -506,6 +551,7 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f
|
|||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y=
|
||||
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
|
@ -558,30 +604,31 @@ gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|||
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.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
|
||||
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
|
||||
helm.sh/helm/v3 v3.13.1 h1:DG+XLGzBJeZvMLlMbm6bPDLV1dGaVW9eZsDoUd1/LM0=
|
||||
helm.sh/helm/v3 v3.13.1/go.mod h1:TdQRMiq46CSWcc68Hb0uVhvAWusaN90YwAV54cz6JzU=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
k8s.io/api v0.28.3 h1:Gj1HtbSdB4P08C8rs9AR94MfSGpRhJgsS+GF9V26xMM=
|
||||
k8s.io/api v0.28.3/go.mod h1:MRCV/jr1dW87/qJnZ57U5Pak65LGmQVkKTzf3AtKFHc=
|
||||
k8s.io/apiextensions-apiserver v0.28.2 h1:J6/QRWIKV2/HwBhHRVITMLYoypCoPY1ftigDM0Kn+QU=
|
||||
k8s.io/apiextensions-apiserver v0.28.2/go.mod h1:5tnkxLGa9nefefYzWuAlWZ7RZYuN/765Au8cWLA6SRg=
|
||||
k8s.io/apiextensions-apiserver v0.28.3 h1:Od7DEnhXHnHPZG+W9I97/fSQkVpVPQx2diy+2EtmY08=
|
||||
k8s.io/apiextensions-apiserver v0.28.3/go.mod h1:NE1XJZ4On0hS11aWWJUTNkmVB03j9LM7gJSisbRt8Lc=
|
||||
k8s.io/apimachinery v0.28.3 h1:B1wYx8txOaCQG0HmYF6nbpU8dg6HvA06x5tEffvOe7A=
|
||||
k8s.io/apimachinery v0.28.3/go.mod h1:uQTKmIqs+rAYaq+DFaoD2X7pcjLOqbQX2AOiO0nIpb8=
|
||||
k8s.io/apiserver v0.28.2 h1:rBeYkLvF94Nku9XfXyUIirsVzCzJBs6jMn3NWeHieyI=
|
||||
k8s.io/apiserver v0.28.2/go.mod h1:f7D5e8wH8MWcKD7azq6Csw9UN+CjdtXIVQUyUhrtb+E=
|
||||
k8s.io/cli-runtime v0.28.2 h1:64meB2fDj10/ThIMEJLO29a1oujSm0GQmKzh1RtA/uk=
|
||||
k8s.io/cli-runtime v0.28.2/go.mod h1:bTpGOvpdsPtDKoyfG4EG041WIyFZLV9qq4rPlkyYfDA=
|
||||
k8s.io/apiserver v0.28.3 h1:8Ov47O1cMyeDzTXz0rwcfIIGAP/dP7L8rWbEljRcg5w=
|
||||
k8s.io/apiserver v0.28.3/go.mod h1:YIpM+9wngNAv8Ctt0rHG4vQuX/I5rvkEMtZtsxW2rNM=
|
||||
k8s.io/cli-runtime v0.28.3 h1:lvuJYVkwCqHEvpS6KuTZsUVwPePFjBfSGvuaLl2SxzA=
|
||||
k8s.io/cli-runtime v0.28.3/go.mod h1:jeX37ZPjIcENVuXDDTskG3+FnVuZms5D9omDXS/2Jjc=
|
||||
k8s.io/client-go v0.28.3 h1:2OqNb72ZuTZPKCl+4gTKvqao0AMOl9f3o2ijbAj3LI4=
|
||||
k8s.io/client-go v0.28.3/go.mod h1:LTykbBp9gsA7SwqirlCXBWtK0guzfhpoW4qSm7i9dxo=
|
||||
k8s.io/component-base v0.28.2 h1:Yc1yU+6AQSlpJZyvehm/NkJBII72rzlEsd6MkBQ+G0E=
|
||||
k8s.io/component-base v0.28.2/go.mod h1:4IuQPQviQCg3du4si8GpMrhAIegxpsgPngPRR/zWpzc=
|
||||
k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
|
||||
k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
|
||||
k8s.io/component-base v0.28.3 h1:rDy68eHKxq/80RiMb2Ld/tbH8uAE75JdCqJyi6lXMzI=
|
||||
k8s.io/component-base v0.28.3/go.mod h1:fDJ6vpVNSk6cRo5wmDa6eKIG7UlIQkaFmZN2fYgIUD8=
|
||||
k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
|
||||
k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ=
|
||||
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM=
|
||||
k8s.io/kubectl v0.28.2 h1:fOWOtU6S0smdNjG1PB9WFbqEIMlkzU5ahyHkc7ESHgM=
|
||||
k8s.io/kubectl v0.28.2/go.mod h1:6EQWTPySF1fn7yKoQZHYf9TPwIl2AygHEcJoxFekr64=
|
||||
k8s.io/kubectl v0.28.3 h1:H1Peu1O3EbN9zHkJCcvhiJ4NUj6lb88sGPO5wrWIM6k=
|
||||
k8s.io/kubectl v0.28.3/go.mod h1:RDAudrth/2wQ3Sg46fbKKl4/g+XImzvbsSRZdP2RiyE=
|
||||
k8s.io/metrics v0.28.3 h1:w2s3kVi7HulXqCVDFkF4hN/OsL1tXTTb4Biif995h/g=
|
||||
k8s.io/metrics v0.28.3/go.mod h1:OZZ23AHFojPzU6r3xoHGRUcV3I9pauLua+07sAUbwLc=
|
||||
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk=
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import (
|
|||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||
metricsapi "k8s.io/metrics/pkg/apis/metrics"
|
||||
"k8s.io/metrics/pkg/client/clientset/versioned"
|
||||
)
|
||||
|
|
@ -32,6 +33,9 @@ const (
|
|||
|
||||
var supportedMetricsAPIVersions = []string{"v1beta1"}
|
||||
|
||||
// Namespaces tracks a collection of namespace names.
|
||||
type Namespaces map[string]struct{}
|
||||
|
||||
// APIClient represents a Kubernetes api client.
|
||||
type APIClient struct {
|
||||
client, logClient kubernetes.Interface
|
||||
|
|
@ -209,7 +213,7 @@ func (a *APIClient) ServerVersion() (*version.Info, error) {
|
|||
// ValidNamespaces returns all available namespaces.
|
||||
func (a *APIClient) ValidNamespaces() ([]v1.Namespace, error) {
|
||||
if a == nil {
|
||||
return []v1.Namespace{}, nil
|
||||
return nil, fmt.Errorf("validNamespaces: no available client found")
|
||||
}
|
||||
|
||||
if nn, ok := a.cache.Get("validNamespaces"); ok {
|
||||
|
|
@ -282,6 +286,9 @@ func (a *APIClient) Config() *Config {
|
|||
// HasMetrics checks if the cluster supports metrics.
|
||||
func (a *APIClient) HasMetrics() bool {
|
||||
err := a.supportsMetricsResources()
|
||||
if err != nil {
|
||||
log.Debug().Msgf("Metrics server detect failed: %s", err)
|
||||
}
|
||||
return err == nil
|
||||
}
|
||||
|
||||
|
|
@ -348,6 +355,7 @@ func (a *APIClient) CachedDiscovery() (*disk.CachedDiscoveryClient, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
httpCacheDir := filepath.Join(mustHomeDir(), ".kube", "http-cache")
|
||||
discCacheDir := filepath.Join(mustHomeDir(), ".kube", "cache", "discovery", toHostDir(cfg.Host))
|
||||
|
||||
|
|
@ -446,7 +454,9 @@ func (a *APIClient) supportsMetricsResources() error {
|
|||
a.cache.Add(cacheMXAPIKey, supported, cacheExpiry)
|
||||
}()
|
||||
|
||||
dial, err := a.CachedDiscovery()
|
||||
cfg := cmdutil.NewMatchVersionFlags(a.config.flags)
|
||||
f := cmdutil.NewFactory(cfg)
|
||||
dial, err := f.ToDiscoveryClient()
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Msgf("Unable to dial discovery API")
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -149,8 +149,8 @@ func (c *Config) RenameContext(old string, new string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := clientcmd.ModifyConfig(acc, cfg, true); err != nil {
|
||||
return err
|
||||
if e := clientcmd.ModifyConfig(acc, cfg, true); e != nil {
|
||||
return e
|
||||
}
|
||||
current, err := c.CurrentContextName()
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -70,8 +70,8 @@ func (l *LogItem) Render(paint string, showTime bool, bb *bytes.Buffer) {
|
|||
bb.WriteString("[gray::b]")
|
||||
bb.Write(l.Bytes[:index])
|
||||
bb.WriteString(" ")
|
||||
for i := len(l.Bytes[:index]); i < 30; i++ {
|
||||
bb.WriteByte(' ')
|
||||
if l := 30 - len(l.Bytes[:index]); l > 0 {
|
||||
bb.Write(bytes.Repeat([]byte{' '}, l))
|
||||
}
|
||||
bb.WriteString("[-::-]")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ func TestLogItemRender(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func BenchmarkLogItemRender(b *testing.B) {
|
||||
func BenchmarkLogItemRenderTS(b *testing.B) {
|
||||
s := []byte(fmt.Sprintf("%s %s\n", "2018-12-14T10:36:43.326972-07:00", "Testing 1,2,3..."))
|
||||
i := dao.NewLogItem(s)
|
||||
i.Pod, i.Container = "fred", "blee"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package dao
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
|
|
@ -83,7 +84,9 @@ func (o DrainOptions) toDrainHelper(k kubernetes.Interface, w io.Writer) drain.H
|
|||
|
||||
// Drain drains a node.
|
||||
func (n *Node) Drain(path string, opts DrainOptions, w io.Writer) error {
|
||||
_ = n.ToggleCordon(path, true)
|
||||
if err := n.ToggleCordon(path, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dial, err := n.GetFactory().Client().Dial()
|
||||
if err != nil {
|
||||
|
|
@ -97,7 +100,7 @@ func (n *Node) Drain(path string, opts DrainOptions, w io.Writer) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
return errs[0]
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
|
||||
if err := h.DeleteOrEvictPods(dd.Pods()); err != nil {
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ func (p *Pod) GetInstance(fqn string) (*v1.Pod, error) {
|
|||
func (p *Pod) TailLogs(ctx context.Context, opts *LogOptions) ([]LogChan, error) {
|
||||
fac, ok := ctx.Value(internal.KeyFactory).(*watch.Factory)
|
||||
if !ok {
|
||||
return nil, errors.New("No factory in context")
|
||||
return nil, errors.New("no factory in context")
|
||||
}
|
||||
o, err := fac.Get(p.gvr.String(), opts.Path, true, labels.Everything())
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,107 @@
|
|||
package dialog
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/derailed/k9s/internal/config"
|
||||
"github.com/derailed/k9s/internal/ui"
|
||||
"github.com/derailed/tview"
|
||||
)
|
||||
|
||||
const confirmKey = "confirm"
|
||||
|
||||
type TransferFn func(from, to, co string, download, no_preserve bool) bool
|
||||
|
||||
type TransferDialogOpts struct {
|
||||
Containers []string
|
||||
Pod string
|
||||
Title, Message string
|
||||
Ack TransferFn
|
||||
Cancel cancelFunc
|
||||
}
|
||||
|
||||
func ShowUploads(styles config.Dialog, pages *ui.Pages, opts TransferDialogOpts) {
|
||||
f := tview.NewForm()
|
||||
f.SetItemPadding(0)
|
||||
f.SetButtonsAlign(tview.AlignCenter).
|
||||
SetButtonBackgroundColor(styles.ButtonBgColor.Color()).
|
||||
SetButtonTextColor(styles.ButtonFgColor.Color()).
|
||||
SetLabelColor(styles.LabelFgColor.Color()).
|
||||
SetFieldTextColor(styles.FieldFgColor.Color())
|
||||
f.AddButton("Cancel", func() {
|
||||
dismissConfirm(pages)
|
||||
opts.Cancel()
|
||||
})
|
||||
|
||||
modal := tview.NewModalForm("<"+opts.Title+">", f)
|
||||
|
||||
from, to := opts.Pod, ""
|
||||
var fromField, toField *tview.InputField
|
||||
download := true
|
||||
f.AddCheckbox("Download:", download, func(_ string, flag bool) {
|
||||
if flag {
|
||||
modal.SetText(strings.Replace(opts.Message, "Upload", "Download", 1))
|
||||
} else {
|
||||
modal.SetText(strings.Replace(opts.Message, "Download", "Upload", 1))
|
||||
}
|
||||
download = flag
|
||||
from, to = to, from
|
||||
fromField.SetText(from)
|
||||
toField.SetText(to)
|
||||
})
|
||||
|
||||
f.AddInputField("From:", from, 40, nil, func(t string) {
|
||||
from = t
|
||||
})
|
||||
f.AddInputField("To:", to, 40, nil, func(t string) {
|
||||
to = t
|
||||
})
|
||||
fromField, _ = f.GetFormItemByLabel("From:").(*tview.InputField)
|
||||
toField, _ = f.GetFormItemByLabel("To:").(*tview.InputField)
|
||||
|
||||
var no_preserve bool
|
||||
f.AddCheckbox("NoPreserve:", no_preserve, func(_ string, f bool) {
|
||||
no_preserve = f
|
||||
})
|
||||
var co string
|
||||
if len(opts.Containers) > 0 {
|
||||
co = opts.Containers[0]
|
||||
}
|
||||
f.AddInputField("Container:", co, 30, nil, func(t string) {
|
||||
co = t
|
||||
})
|
||||
|
||||
f.AddButton("OK", func() {
|
||||
if !opts.Ack(from, to, co, download, no_preserve) {
|
||||
return
|
||||
}
|
||||
dismissConfirm(pages)
|
||||
opts.Cancel()
|
||||
})
|
||||
for i := 0; i < 2; i++ {
|
||||
b := f.GetButton(i)
|
||||
if b == nil {
|
||||
continue
|
||||
}
|
||||
b.SetBackgroundColorActivated(styles.ButtonFocusBgColor.Color())
|
||||
b.SetLabelColorActivated(styles.ButtonFocusFgColor.Color())
|
||||
}
|
||||
f.SetFocus(0)
|
||||
|
||||
message := opts.Message
|
||||
if len(opts.Containers) > 1 {
|
||||
message += "\nAvailable Containers:" + strings.Join(opts.Containers, ",")
|
||||
}
|
||||
modal.SetText(message)
|
||||
modal.SetTextColor(styles.FgColor.Color())
|
||||
modal.SetDoneFunc(func(int, string) {
|
||||
dismissConfirm(pages)
|
||||
opts.Cancel()
|
||||
})
|
||||
pages.AddPage(confirmKey, modal, false, false)
|
||||
pages.ShowPage(confirmKey)
|
||||
}
|
||||
|
||||
func dismissConfirm(pages *ui.Pages) {
|
||||
pages.RemovePage(confirmKey)
|
||||
}
|
||||
|
|
@ -169,10 +169,9 @@ func (m *Menu) formatMenu(h model.MenuHint, size int) string {
|
|||
// Helpers...
|
||||
|
||||
func keyConv(s string) string {
|
||||
if !strings.Contains(s, "alt") {
|
||||
if s == "" || !strings.Contains(s, "alt") {
|
||||
return s
|
||||
}
|
||||
|
||||
if runtime.GOOS != "darwin" {
|
||||
return s
|
||||
}
|
||||
|
|
@ -185,8 +184,8 @@ func Truncate(str string, width int) string {
|
|||
return runewidth.Truncate(str, width, string(tview.SemigraphicsHorizontalEllipsis))
|
||||
}
|
||||
|
||||
func toMnemonic(s string) string {
|
||||
if len(s) == 0 {
|
||||
func ToMnemonic(s string) string {
|
||||
if s == "" {
|
||||
return s
|
||||
}
|
||||
|
||||
|
|
@ -197,6 +196,7 @@ func formatNSMenu(i int, name string, styles config.Frame) string {
|
|||
fmat := strings.Replace(menuIndexFmt, "[key", "["+styles.Menu.NumKeyColor.String(), 1)
|
||||
fmat = strings.Replace(fmat, ":bg:", ":"+styles.Title.BgColor.String()+":", -1)
|
||||
fmat = strings.Replace(fmat, "[fg", "["+styles.Menu.FgColor.String(), 1)
|
||||
|
||||
return fmt.Sprintf(fmat, i, name)
|
||||
}
|
||||
|
||||
|
|
@ -205,5 +205,6 @@ func formatPlainMenu(h model.MenuHint, size int, styles config.Frame) string {
|
|||
fmat := strings.Replace(menuFmt, "[key", "["+styles.Menu.KeyColor.String(), 1)
|
||||
fmat = strings.Replace(fmat, "[fg", "["+styles.Menu.FgColor.String(), 1)
|
||||
fmat = strings.Replace(fmat, ":bg:", ":"+styles.Title.BgColor.String()+":", -1)
|
||||
return fmt.Sprintf(fmat, toMnemonic(h.Mnemonic), h.Description)
|
||||
|
||||
return fmt.Sprintf(fmat, ToMnemonic(h.Mnemonic), h.Description)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,11 +31,12 @@ type (
|
|||
|
||||
// Table represents tabular data.
|
||||
type Table struct {
|
||||
gvr client.GVR
|
||||
sortCol SortColumn
|
||||
header render.Header
|
||||
Path string
|
||||
Extras string
|
||||
gvr client.GVR
|
||||
sortCol SortColumn
|
||||
manualSort bool
|
||||
header render.Header
|
||||
Path string
|
||||
Extras string
|
||||
*SelectTable
|
||||
actions KeyActions
|
||||
cmdBuff *model.FishBuff
|
||||
|
|
@ -46,7 +47,6 @@ type Table struct {
|
|||
wide bool
|
||||
toast bool
|
||||
hasMetrics bool
|
||||
manualSort bool
|
||||
}
|
||||
|
||||
// NewTable returns a new table view.
|
||||
|
|
@ -86,8 +86,7 @@ func (t *Table) GVR() client.GVR { return t.gvr }
|
|||
|
||||
// ViewSettingsChanged notifies listener the view configuration changed.
|
||||
func (t *Table) ViewSettingsChanged(settings config.ViewSetting) {
|
||||
t.manualSort = false // make user changes to the sortColumn take effect
|
||||
t.viewSetting = &settings
|
||||
t.viewSetting, t.manualSort = &settings, false
|
||||
t.Refresh()
|
||||
}
|
||||
|
||||
|
|
@ -208,7 +207,7 @@ func (t *Table) doUpdate(data *render.TableData) {
|
|||
// if the sortCol has not been modified manually
|
||||
if t.viewSetting != nil && t.viewSetting.SortColumn != "" && !t.manualSort {
|
||||
tokens := strings.Split(t.viewSetting.SortColumn, ":")
|
||||
if custData.Header.IndexOf(tokens[0], false) >= 0 {
|
||||
if custData.Header.IndexOf(tokens[0], false) >= 0 && !t.manualSort {
|
||||
t.sortCol.name, t.sortCol.asc = tokens[0], true
|
||||
if len(tokens) == 2 && tokens[1] == "desc" {
|
||||
t.sortCol.asc = false
|
||||
|
|
@ -315,6 +314,7 @@ func (t *Table) buildRow(r int, re, ore render.RowEvent, h render.Header, pads M
|
|||
// SortColCmd designates a sorted column.
|
||||
func (t *Table) SortColCmd(name string, asc bool) func(evt *tcell.EventKey) *tcell.EventKey {
|
||||
return func(evt *tcell.EventKey) *tcell.EventKey {
|
||||
t.manualSort = true
|
||||
t.sortCol.asc = !t.sortCol.asc
|
||||
if t.sortCol.name != name {
|
||||
t.sortCol.asc = asc
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package view
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
|
|
@ -101,7 +102,7 @@ func pluginActions(r Runner, aa ui.KeyActions) {
|
|||
}
|
||||
_, ok := aa[key]
|
||||
if ok {
|
||||
log.Warn().Err(fmt.Errorf("Doh! you are trying to override an existing command `%s", k)).Msg("Invalid shortcut")
|
||||
log.Warn().Msgf("Invalid shortcut. You are trying to override an existing command `%s", k)
|
||||
continue
|
||||
}
|
||||
aa[key] = ui.NewKeyAction(
|
||||
|
|
@ -139,11 +140,20 @@ func pluginAction(r Runner, p config.Plugin) ui.ActionHandler {
|
|||
pipes: p.Pipes,
|
||||
args: args,
|
||||
}
|
||||
if run(r.App(), opts) {
|
||||
r.App().Flash().Info("Plugin command launched successfully!")
|
||||
suspend, errChan := run(r.App(), opts)
|
||||
if !suspend {
|
||||
r.App().Flash().Info("Plugin command failed!")
|
||||
return
|
||||
}
|
||||
r.App().Flash().Info("Plugin command failed!")
|
||||
var errs error
|
||||
for e := range errChan {
|
||||
errs = errors.Join(errs, e)
|
||||
}
|
||||
if errs != nil {
|
||||
r.App().cowCmd(errs.Error())
|
||||
return
|
||||
}
|
||||
r.App().Flash().Info("Plugin command launched successfully!")
|
||||
}
|
||||
if p.Confirm {
|
||||
msg := fmt.Sprintf("Run?\n%s %s", p.Command, strings.Join(args, " "))
|
||||
|
|
|
|||
|
|
@ -89,14 +89,14 @@ func (a *App) Init(version string, rate int) error {
|
|||
a.SetInputCapture(a.keyboard)
|
||||
a.bindKeys()
|
||||
if a.Conn() == nil {
|
||||
return errors.New("No client connection detected")
|
||||
return errors.New("no client connection detected")
|
||||
}
|
||||
ns := a.Config.ActiveNamespace()
|
||||
|
||||
a.factory = watch.NewFactory(a.Conn())
|
||||
ok, err := a.isValidNS(ns)
|
||||
if !ok && err == nil {
|
||||
return fmt.Errorf("Invalid namespace %s", ns)
|
||||
return fmt.Errorf("invalid namespace %s", ns)
|
||||
}
|
||||
a.initFactory(ns)
|
||||
|
||||
|
|
@ -206,8 +206,7 @@ func (a *App) ActiveView() model.Component {
|
|||
}
|
||||
|
||||
func (a *App) toggleHeader(header, logo bool) {
|
||||
a.showHeader = header
|
||||
a.showLogo = logo
|
||||
a.showHeader, a.showLogo = header, logo
|
||||
flex, ok := a.Main.GetPrimitive("main").(*tview.Flex)
|
||||
if !ok {
|
||||
log.Fatal().Msg("Expecting valid flex view")
|
||||
|
|
@ -285,7 +284,7 @@ func (a *App) Resume() {
|
|||
}
|
||||
|
||||
func (a *App) clusterUpdater(ctx context.Context) {
|
||||
if err := a.refreshCluster(); err != nil {
|
||||
if err := a.refreshCluster(ctx); err != nil {
|
||||
log.Error().Err(err).Msgf("Cluster updater failed!")
|
||||
return
|
||||
}
|
||||
|
|
@ -298,7 +297,7 @@ func (a *App) clusterUpdater(ctx context.Context) {
|
|||
log.Debug().Msg("ClusterInfo updater canceled!")
|
||||
return
|
||||
case <-time.After(delay):
|
||||
if err := a.refreshCluster(); err != nil {
|
||||
if err := a.refreshCluster(ctx); err != nil {
|
||||
log.Error().Err(err).Msgf("ClusterUpdater failed")
|
||||
if delay = bf.NextBackOff(); delay == backoff.Stop {
|
||||
a.BailOut()
|
||||
|
|
@ -312,7 +311,7 @@ func (a *App) clusterUpdater(ctx context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
func (a *App) refreshCluster() error {
|
||||
func (a *App) refreshCluster(context.Context) error {
|
||||
c := a.Content.Top()
|
||||
if ok := a.Conn().CheckConnectivity(); ok {
|
||||
if atomic.LoadInt32(&a.conRetry) > 0 {
|
||||
|
|
@ -338,7 +337,7 @@ func (a *App) refreshCluster() error {
|
|||
}
|
||||
if count > 0 {
|
||||
a.Status(model.FlashWarn, fmt.Sprintf("Dial K8s Toast [%d/%d]", count, maxConnRetry))
|
||||
return fmt.Errorf("Conn check failed (%d/%d)", count, maxConnRetry)
|
||||
return fmt.Errorf("conn check failed (%d/%d)", count, maxConnRetry)
|
||||
}
|
||||
|
||||
// Reload alias
|
||||
|
|
@ -367,7 +366,7 @@ func (a *App) switchNS(ns string) error {
|
|||
return err
|
||||
}
|
||||
if !ok {
|
||||
return fmt.Errorf("Invalid namespace %q", ns)
|
||||
return fmt.Errorf("invalid namespace %q", ns)
|
||||
}
|
||||
if err := a.Config.SetActiveNamespace(ns); err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package view
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
|
@ -145,7 +144,7 @@ func (b *Browser) Start() {
|
|||
b.Table.Start()
|
||||
b.CmdBuff().AddListener(b)
|
||||
if err := b.GetModel().Watch(b.prepareContext()); err != nil {
|
||||
b.App().Flash().Err(fmt.Errorf("Watcher failed for %s -- %w", b.GVR(), err))
|
||||
b.App().Flash().Errf("Watcher failed for %s -- %s", b.GVR(), err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -373,7 +372,7 @@ func (b *Browser) editCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
ns = n
|
||||
}
|
||||
if ok, err := b.app.Conn().CanI(ns, b.GVR().String(), []string{"patch"}); !ok || err != nil {
|
||||
b.App().Flash().Err(fmt.Errorf("Current user can't edit resource %s", b.GVR()))
|
||||
b.App().Flash().Errf("Current user can't edit resource %s", b.GVR())
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -386,8 +385,8 @@ func (b *Browser) editCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
if ns != client.AllNamespaces {
|
||||
args = append(args, "-n", ns)
|
||||
}
|
||||
if !runK(b.app, shellOpts{clear: true, args: args}) {
|
||||
b.app.Flash().Err(errors.New("Edit exec failed"))
|
||||
if err := runK(b.app, shellOpts{clear: true, args: args}); err != nil {
|
||||
b.app.Flash().Errf("Edit command failed: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -543,7 +542,7 @@ func (b *Browser) simpleDelete(selections []string, msg string) {
|
|||
}
|
||||
|
||||
func (b *Browser) resourceDelete(selections []string, msg string) {
|
||||
dialog.ShowDelete(b.app.Styles.Dialog(), b.app.Content.Pages, msg, func(propagation *metav1.DeletionPropagation, force bool) {
|
||||
okFn := func(propagation *metav1.DeletionPropagation, force bool) {
|
||||
b.ShowDeleted()
|
||||
if len(selections) > 1 {
|
||||
b.app.Flash().Infof("Delete %d marked %s", len(selections), b.GVR())
|
||||
|
|
@ -563,5 +562,6 @@ func (b *Browser) resourceDelete(selections []string, msg string) {
|
|||
b.GetTable().DeleteMark(sel)
|
||||
}
|
||||
b.refresh()
|
||||
}, func() {})
|
||||
}
|
||||
dialog.ShowDelete(b.app.Styles.Dialog(), b.app.Content.Pages, msg, okFn, func() {})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ func allowedXRay(gvr client.GVR) bool {
|
|||
func (c *Command) xrayCmd(cmd string) error {
|
||||
tokens := strings.Split(cmd, " ")
|
||||
if len(tokens) < 2 {
|
||||
return errors.New("You must specify a resource")
|
||||
return errors.New("you must specify a resource")
|
||||
}
|
||||
gvr, ok := c.alias.AsGVR(tokens[1])
|
||||
if !ok {
|
||||
|
|
@ -108,7 +108,7 @@ func (c *Command) xrayCmd(cmd string) error {
|
|||
return c.exec(cmd, "xrays", x, true)
|
||||
}
|
||||
|
||||
// Exec the Command by showing associated display.
|
||||
// Run execs the command by showing associated display.
|
||||
func (c *Command) run(cmd, path string, clearStack bool) error {
|
||||
if c.specialCmd(cmd, path) {
|
||||
return nil
|
||||
|
|
@ -119,6 +119,11 @@ func (c *Command) run(cmd, path string, clearStack bool) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var cns string
|
||||
tt := strings.Split(gvr, " ")
|
||||
if len(tt) == 2 {
|
||||
gvr, cns = tt[0], tt[1]
|
||||
}
|
||||
|
||||
switch command {
|
||||
case "ctx", "context", "contexts":
|
||||
|
|
@ -128,7 +133,7 @@ func (c *Command) run(cmd, path string, clearStack bool) error {
|
|||
return c.exec(cmd, gvr, c.componentFor(gvr, path, v), clearStack)
|
||||
case "dir":
|
||||
if len(cmds) != 2 {
|
||||
return errors.New("You must specify a directory")
|
||||
return errors.New("you must specify a directory")
|
||||
}
|
||||
return c.app.dirCmd(cmds[1])
|
||||
default:
|
||||
|
|
@ -137,6 +142,9 @@ func (c *Command) run(cmd, path string, clearStack bool) error {
|
|||
if len(cmds) == 2 {
|
||||
ns = cmds[1]
|
||||
}
|
||||
if cns != "" {
|
||||
ns = cns
|
||||
}
|
||||
if err := c.app.switchNS(ns); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -254,12 +262,12 @@ func (c *Command) exec(cmd, gvr string, comp model.Component, clearStack bool) (
|
|||
} else {
|
||||
_ = c.run(hh[0], "", true)
|
||||
}
|
||||
err = fmt.Errorf("Invalid command %q", cmd)
|
||||
err = fmt.Errorf("invalid command %q", cmd)
|
||||
}
|
||||
}()
|
||||
|
||||
if comp == nil {
|
||||
return fmt.Errorf("No component found for %s", gvr)
|
||||
return fmt.Errorf("no component found for %s", gvr)
|
||||
}
|
||||
c.app.Flash().Infof("Viewing %s...", client.NewGVR(gvr).R())
|
||||
if tokens := strings.Split(cmd, " "); len(tokens) >= 2 {
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ func (c *Container) portFwdCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
}
|
||||
|
||||
if _, ok := c.App().factory.ForwarderFor(fwFQN(c.GetTable().Path, path)); ok {
|
||||
c.App().Flash().Err(fmt.Errorf("A port-forward already exists on container %s", c.GetTable().Path))
|
||||
c.App().Flash().Errf("A port-forward already exists on container %s", c.GetTable().Path)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -118,12 +118,12 @@ func useContext(app *App, name string) error {
|
|||
}
|
||||
switcher, ok := res.(dao.Switchable)
|
||||
if !ok {
|
||||
return errors.New("Expecting a switchable resource")
|
||||
return errors.New("expecting a switchable resource")
|
||||
}
|
||||
if err := switcher.Switch(name); err != nil {
|
||||
log.Error().Err(err).Msgf("Context switch failed")
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
return app.switchContext(name)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package view
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
|
@ -121,7 +120,7 @@ func (d *Dir) editCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
d.Stop()
|
||||
defer d.Start()
|
||||
if !edit(d.App(), shellOpts{clear: true, args: []string{sel}}) {
|
||||
d.App().Flash().Err(errors.New("Failed to launch editor"))
|
||||
d.App().Flash().Errf("Failed to launch editor")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
@ -230,18 +229,18 @@ func (d *Dir) delCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
}
|
||||
|
||||
opts := []string{"-f"}
|
||||
msgRessource := "manifest"
|
||||
msgResource := "manifest"
|
||||
if containsDir(sel) {
|
||||
opts = append(opts, "-R")
|
||||
}
|
||||
if isKustomized(sel) {
|
||||
opts = []string{"-k"}
|
||||
msgRessource = "kustomization"
|
||||
msgResource = "kustomization"
|
||||
}
|
||||
|
||||
d.Stop()
|
||||
defer d.Start()
|
||||
msg := fmt.Sprintf("Delete resource(s) in %s %s", msgRessource, sel)
|
||||
msg := fmt.Sprintf("Delete resource(s) in %s %s", msgResource, sel)
|
||||
dialog.ShowConfirm(d.App().Styles.Dialog(), d.App().Content.Pages, "Confirm Delete", msg, func() {
|
||||
args := make([]string, 0, 10)
|
||||
args = append(args, "delete")
|
||||
|
|
|
|||
|
|
@ -39,15 +39,17 @@ type shellOpts struct {
|
|||
args []string
|
||||
}
|
||||
|
||||
func runK(a *App, opts shellOpts) bool {
|
||||
func (s shellOpts) String() string {
|
||||
return fmt.Sprintf("%s %s", s.binary, strings.Join(s.args, " "))
|
||||
}
|
||||
|
||||
func runK(a *App, opts shellOpts) 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 false
|
||||
return fmt.Errorf("kubectl command must not be in the current working directory: %w", err)
|
||||
}
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msgf("kubectl command is not in your path")
|
||||
return false
|
||||
return fmt.Errorf("kubectl command is not in your path: %w", err)
|
||||
}
|
||||
args := []string{opts.args[0]}
|
||||
if u, err := a.Conn().Config().ImpersonateUser(); err == nil {
|
||||
|
|
@ -66,20 +68,42 @@ func runK(a *App, opts shellOpts) bool {
|
|||
if len(args) > 0 {
|
||||
opts.args = append(args, opts.args[1:]...)
|
||||
}
|
||||
opts.binary, opts.background = bin, false
|
||||
opts.binary = bin
|
||||
|
||||
return run(a, opts)
|
||||
suspended, errChan := run(a, opts)
|
||||
if !suspended {
|
||||
return fmt.Errorf("unable to run command")
|
||||
}
|
||||
var errs error
|
||||
for e := range errChan {
|
||||
errs = errors.Join(errs, e)
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
func run(a *App, opts shellOpts) bool {
|
||||
func run(a *App, opts shellOpts) (bool, chan error) {
|
||||
errChan := make(chan error, 1)
|
||||
|
||||
if opts.background {
|
||||
if err := execute(opts); err != nil {
|
||||
errChan <- err
|
||||
a.Flash().Errf("Exec failed %q: %s", opts, err)
|
||||
}
|
||||
close(errChan)
|
||||
return true, errChan
|
||||
}
|
||||
|
||||
a.Halt()
|
||||
defer a.Resume()
|
||||
|
||||
return a.Suspend(func() {
|
||||
if err := execute(opts); err != nil {
|
||||
a.Flash().Errf("Command exited: %v", err)
|
||||
errChan <- err
|
||||
a.Flash().Errf("Exec failed %q: %s", opts, err)
|
||||
}
|
||||
})
|
||||
close(errChan)
|
||||
}), errChan
|
||||
}
|
||||
|
||||
func edit(a *App, opts shellOpts) bool {
|
||||
|
|
@ -93,7 +117,15 @@ func edit(a *App, opts shellOpts) bool {
|
|||
}
|
||||
opts.binary, opts.background = bin, false
|
||||
|
||||
return run(a, opts)
|
||||
suspended, errChan := run(a, opts)
|
||||
if !suspended {
|
||||
a.Flash().Errf("edit command failed")
|
||||
}
|
||||
for e := range errChan {
|
||||
a.Flash().Err(e)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func execute(opts shellOpts) error {
|
||||
|
|
@ -113,8 +145,8 @@ func execute(opts shellOpts) error {
|
|||
go func(cancel context.CancelFunc) {
|
||||
defer log.Debug().Msgf("SIGNAL_GOR - BAILED!!")
|
||||
select {
|
||||
case <-sigChan:
|
||||
log.Debug().Msgf("Command canceled with signal!")
|
||||
case sig := <-sigChan:
|
||||
log.Debug().Msgf("Command canceled with signal! %#v", sig)
|
||||
cancel()
|
||||
case <-ctx.Done():
|
||||
log.Debug().Msgf("SIGNAL Context CANCELED!")
|
||||
|
|
@ -123,7 +155,7 @@ func execute(opts shellOpts) error {
|
|||
|
||||
cmds := make([]*exec.Cmd, 0, 1)
|
||||
cmd := exec.CommandContext(ctx, opts.binary, opts.args...)
|
||||
log.Debug().Msgf("RUNNING> %s", cmd)
|
||||
log.Debug().Msgf("RUNNING> %s", opts)
|
||||
cmds = append(cmds, cmd)
|
||||
|
||||
for _, p := range opts.pipes {
|
||||
|
|
@ -136,7 +168,14 @@ func execute(opts shellOpts) error {
|
|||
cmds = append(cmds, cmd)
|
||||
}
|
||||
|
||||
return pipe(ctx, opts, cmds...)
|
||||
var o, e bytes.Buffer
|
||||
err := pipe(ctx, opts, &o, &e, cmds...)
|
||||
if err != nil {
|
||||
log.Err(err).Msgf("Command failed")
|
||||
return errors.Join(err, fmt.Errorf("%s", e.String()))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func runKu(a *App, opts shellOpts) (string, error) {
|
||||
|
|
@ -209,18 +248,20 @@ func ssh(a *App, node string) error {
|
|||
}
|
||||
|
||||
cl := a.Config.K9s.ActiveCluster()
|
||||
if cl == nil {
|
||||
return fmt.Errorf("no active cluster detected")
|
||||
}
|
||||
ns := cl.ShellPod.Namespace
|
||||
sshIn(a, client.FQN(ns, k9sShellPodName()), k9sShell)
|
||||
|
||||
return nil
|
||||
return sshIn(a, client.FQN(ns, k9sShellPodName()), k9sShell)
|
||||
}
|
||||
|
||||
func sshIn(a *App, fqn, co string) {
|
||||
func sshIn(a *App, fqn, co string) error {
|
||||
cl := a.Config.K9s.ActiveCluster()
|
||||
cfg := cl.ShellPod
|
||||
os, err := getPodOS(a.factory, fqn)
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Msgf("os detect failed")
|
||||
return fmt.Errorf("os detect failed: %w", err)
|
||||
}
|
||||
|
||||
args := buildShellArgs("exec", fqn, co, a.Conn().Config().Flags().KubeConfig)
|
||||
|
|
@ -237,9 +278,12 @@ func sshIn(a *App, fqn, co string) {
|
|||
log.Debug().Msgf("ARGS %#v", args)
|
||||
|
||||
c := color.New(color.BgGreen).Add(color.FgBlack).Add(color.Bold)
|
||||
if !runK(a, shellOpts{clear: true, banner: c.Sprintf(bannerFmt, fqn, co), args: args}) {
|
||||
a.Flash().Err(errors.New("Shell exec failed"))
|
||||
err = runK(a, shellOpts{clear: true, banner: c.Sprintf(bannerFmt, fqn, co), args: args})
|
||||
if err != nil {
|
||||
return fmt.Errorf("shell exec failed: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func nukeK9sShell(a *App) error {
|
||||
|
|
@ -300,7 +344,7 @@ func launchShellPod(a *App, node string) error {
|
|||
time.Sleep(k9sShellRetryDelay)
|
||||
}
|
||||
|
||||
return fmt.Errorf("Unable to launch shell pod on node %s", node)
|
||||
return fmt.Errorf("unable to launch shell pod on node %s", node)
|
||||
}
|
||||
|
||||
func k9sShellPodName() string {
|
||||
|
|
@ -376,7 +420,7 @@ func asResource(r config.Limits) v1.ResourceRequirements {
|
|||
}
|
||||
}
|
||||
|
||||
func pipe(_ context.Context, opts shellOpts, cmds ...*exec.Cmd) error {
|
||||
func pipe(_ context.Context, opts shellOpts, w, e io.Writer, cmds ...*exec.Cmd) error {
|
||||
if len(cmds) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -384,31 +428,17 @@ func pipe(_ context.Context, opts shellOpts, cmds ...*exec.Cmd) error {
|
|||
if len(cmds) == 1 {
|
||||
cmd := cmds[0]
|
||||
if opts.background {
|
||||
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, log.Logger, log.Logger
|
||||
return cmd.Start()
|
||||
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, w, e
|
||||
return cmd.Run()
|
||||
}
|
||||
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
||||
// BOZO!!
|
||||
//cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
//// //Setpgid: true,
|
||||
//// //Setctty: true,
|
||||
// Foreground: true,
|
||||
//}
|
||||
_, _ = cmd.Stdout.Write([]byte(opts.banner))
|
||||
|
||||
log.Debug().Msgf("Running Start")
|
||||
err := cmd.Run()
|
||||
log.Debug().Msgf("Running Done")
|
||||
return err
|
||||
log.Debug().Msgf("Running Done: %s", err)
|
||||
|
||||
// BOZO!!
|
||||
// select {
|
||||
// case <-ctx.Done():
|
||||
// return errors.New("canceled by operator")
|
||||
// default:
|
||||
// log.Debug().Msgf("PIPE RETURN %s", err)
|
||||
// return err
|
||||
// }
|
||||
return err
|
||||
}
|
||||
|
||||
last := len(cmds) - 1
|
||||
|
|
@ -428,8 +458,5 @@ func pipe(_ context.Context, opts shellOpts, cmds ...*exec.Cmd) error {
|
|||
}
|
||||
}
|
||||
|
||||
log.Debug().Msgf("WAITING!!!")
|
||||
err := cmds[len(cmds)-1].Wait()
|
||||
log.Debug().Msgf("DONE WAITING!!!")
|
||||
return err
|
||||
return cmds[len(cmds)-1].Wait()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,8 @@ package view
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/derailed/k9s/internal/client"
|
||||
"github.com/derailed/k9s/internal/config"
|
||||
|
|
@ -296,7 +294,7 @@ func (h *Help) addSection(c int, title string, hh model.MenuHints) {
|
|||
|
||||
for _, hint := range hh {
|
||||
col := c
|
||||
h.SetCell(row, col, padCellWithRef(toMnemonic(hint.Mnemonic), h.maxKey, hint.Mnemonic))
|
||||
h.SetCell(row, col, padCellWithRef(ui.ToMnemonic(hint.Mnemonic), h.maxKey, hint.Mnemonic))
|
||||
col++
|
||||
h.SetCell(row, col, padCell(hint.Description, h.maxDesc))
|
||||
row++
|
||||
|
|
@ -348,14 +346,6 @@ func (h *Help) updateStyle() {
|
|||
// ----------------------------------------------------------------------------
|
||||
// Helpers...
|
||||
|
||||
func toMnemonic(s string) string {
|
||||
if len(s) == 0 {
|
||||
return s
|
||||
}
|
||||
|
||||
return "<" + keyConv(strings.ToLower(s)) + ">"
|
||||
}
|
||||
|
||||
func extractRef(c *tview.TableCell) string {
|
||||
if ref, ok := c.GetReference().(string); ok {
|
||||
return ref
|
||||
|
|
@ -364,18 +354,6 @@ func extractRef(c *tview.TableCell) string {
|
|||
return c.Text
|
||||
}
|
||||
|
||||
func keyConv(s string) string {
|
||||
if !strings.Contains(s, "alt") {
|
||||
return s
|
||||
}
|
||||
|
||||
if runtime.GOOS != "darwin" {
|
||||
return s
|
||||
}
|
||||
|
||||
return strings.Replace(s, "alt", "opt", 1)
|
||||
}
|
||||
|
||||
func (h *Help) titleCell(title string) *tview.TableCell {
|
||||
c := tview.NewTableCell(title)
|
||||
c.SetTextColor(h.Styles().K9s.Help.SectionColor.Color())
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ func TestHelp(t *testing.T) {
|
|||
v := view.NewHelp(app)
|
||||
|
||||
assert.Nil(t, v.Init(ctx))
|
||||
assert.Equal(t, 26, v.GetRowCount())
|
||||
assert.Equal(t, 27, v.GetRowCount())
|
||||
assert.Equal(t, 6, v.GetColumnCount())
|
||||
assert.Equal(t, "<a>", strings.TrimSpace(v.GetCell(1, 0).Text))
|
||||
assert.Equal(t, "Attach", strings.TrimSpace(v.GetCell(1, 1).Text))
|
||||
|
|
|
|||
|
|
@ -81,7 +81,10 @@ func defaultEnv(c *client.Config, path string, header render.Header, row render.
|
|||
env := k8sEnv(c)
|
||||
env["NAMESPACE"], env["NAME"] = client.Namespaced(path)
|
||||
for _, col := range header.Columns(true) {
|
||||
env["COL-"+col] = row.Fields[header.IndexOf(col, true)]
|
||||
i := header.IndexOf(col, true)
|
||||
if i >= 0 && i < len(row.Fields) {
|
||||
env["COL-"+col] = row.Fields[i]
|
||||
}
|
||||
}
|
||||
|
||||
return env
|
||||
|
|
@ -140,7 +143,7 @@ func podCtx(app *App, path, labelSel, fieldSel string) ContextFunc {
|
|||
func extractApp(ctx context.Context) (*App, error) {
|
||||
app, ok := ctx.Value(internal.KeyApp).(*App)
|
||||
if !ok {
|
||||
return nil, errors.New("No application found in context")
|
||||
return nil, errors.New("no application found in context")
|
||||
}
|
||||
|
||||
return app, nil
|
||||
|
|
@ -154,7 +157,7 @@ func asKey(key string) (tcell.Key, error) {
|
|||
}
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf("No matching key found %s", key)
|
||||
return 0, fmt.Errorf("no matching key found %s", key)
|
||||
}
|
||||
|
||||
// FwFQN returns a fully qualified ns/name:container id.
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ func TestExtractApp(t *testing.T) {
|
|||
err error
|
||||
}{
|
||||
"cool": {app: app},
|
||||
"not-cool": {err: errors.New("No application found in context")},
|
||||
"not-cool": {err: errors.New("no application found in context")},
|
||||
}
|
||||
|
||||
for k := range uu {
|
||||
|
|
@ -103,7 +103,7 @@ func TestAsKey(t *testing.T) {
|
|||
e tcell.Key
|
||||
}{
|
||||
"cool": {k: "Ctrl-A", e: tcell.KeyCtrlA},
|
||||
"miss": {k: "fred", e: 0, err: errors.New("No matching key found fred")},
|
||||
"miss": {k: "fred", e: 0, err: errors.New("no matching key found fred")},
|
||||
}
|
||||
|
||||
for k := range uu {
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ var selRx = regexp.MustCompile(`\A([\w-]+)/([\w-]+)\|([\w-]+)?\|(\d+):(\d+)`)
|
|||
func pfToHuman(s string) (string, error) {
|
||||
mm := selRx.FindStringSubmatch(s)
|
||||
if len(mm) < 6 {
|
||||
return "", fmt.Errorf("Unable to parse selection %s", s)
|
||||
return "", fmt.Errorf("unable to parse selection %s", s)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s::%s %s->%s", mm[2], mm[3], mm[4], mm[5]), nil
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ func startFwdCB(v ResourceViewer, path string, pts port.PortTunnels) error {
|
|||
tt := make([]string, 0, len(pts))
|
||||
for _, pt := range pts {
|
||||
if _, ok := v.App().factory.ForwarderFor(dao.PortForwardID(path, pt.Container, pt.PortMap())); ok {
|
||||
return fmt.Errorf("A port-forward is already active on pod %s", path)
|
||||
return fmt.Errorf("port-forward is already active on pod %s", path)
|
||||
}
|
||||
pf := dao.NewPortForwarder(v.App().factory)
|
||||
fwd, err := pf.Start(path, pt)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/derailed/k9s/internal"
|
||||
"github.com/derailed/k9s/internal/client"
|
||||
|
|
@ -11,6 +13,7 @@ import (
|
|||
"github.com/derailed/k9s/internal/model"
|
||||
"github.com/derailed/k9s/internal/render"
|
||||
"github.com/derailed/k9s/internal/ui"
|
||||
"github.com/derailed/k9s/internal/ui/dialog"
|
||||
"github.com/derailed/tcell/v2"
|
||||
"github.com/fatih/color"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
|
@ -26,6 +29,8 @@ const (
|
|||
powerShell = "powershell"
|
||||
osBetaSelector = "beta.kubernetes.io/os"
|
||||
osSelector = "kubernetes.io/os"
|
||||
trUpload = "Upload"
|
||||
trDownload = "Download"
|
||||
)
|
||||
|
||||
// Pod represents a pod viewer.
|
||||
|
|
@ -65,6 +70,7 @@ func (p *Pod) bindDangerousKeys(aa ui.KeyActions) {
|
|||
tcell.KeyCtrlK: ui.NewKeyAction("Kill", p.killCmd, true),
|
||||
ui.KeyS: ui.NewKeyAction("Shell", p.shellCmd, true),
|
||||
ui.KeyA: ui.NewKeyAction("Attach", p.attachCmd, true),
|
||||
ui.KeyT: ui.NewKeyAction("Transfer", p.transferCmd, true),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -249,6 +255,69 @@ func (p *Pod) attachCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *Pod) transferCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||
path := p.GetTable().GetSelectedItem()
|
||||
if path == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
ns, n := client.Namespaced(path)
|
||||
ack := func(from, to, co string, download, no_preserve bool) bool {
|
||||
local := to
|
||||
if !download {
|
||||
local = from
|
||||
}
|
||||
if _, err := os.Stat(local); !download && os.IsNotExist(err) {
|
||||
p.App().Flash().Err(err)
|
||||
return false
|
||||
}
|
||||
|
||||
args := make([]string, 0, 10)
|
||||
args = append(args, "cp")
|
||||
args = append(args, strings.TrimSpace(from))
|
||||
args = append(args, strings.TrimSpace(to))
|
||||
args = append(args, fmt.Sprintf("--no-preserve=%t", no_preserve))
|
||||
if co != "" {
|
||||
args = append(args, "-c="+co)
|
||||
}
|
||||
|
||||
opts := shellOpts{
|
||||
background: true,
|
||||
args: args,
|
||||
}
|
||||
op := trUpload
|
||||
if download {
|
||||
op = trDownload
|
||||
}
|
||||
|
||||
fqn := path + ":" + co
|
||||
if err := runK(p.App(), opts); err != nil {
|
||||
p.App().cowCmd(err.Error())
|
||||
} else {
|
||||
p.App().Flash().Infof("%s successful on %s!", op, fqn)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
pod, err := fetchPod(p.App().factory, path)
|
||||
if err != nil {
|
||||
p.App().Flash().Err(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
opts := dialog.TransferDialogOpts{
|
||||
Title: "Transfer",
|
||||
Containers: fetchContainers(pod.ObjectMeta, pod.Spec, false),
|
||||
Message: "Download Files",
|
||||
Pod: fmt.Sprintf("%s/%s:", ns, n),
|
||||
Ack: ack,
|
||||
Cancel: func() {},
|
||||
}
|
||||
dialog.ShowUploads(p.App().Styles.Dialog(), p.App().Content.Pages, opts)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Helpers...
|
||||
|
||||
|
|
@ -291,8 +360,9 @@ func shellIn(a *App, fqn, co string) {
|
|||
args := computeShellArgs(fqn, co, a.Conn().Config().Flags().KubeConfig, os)
|
||||
|
||||
c := color.New(color.BgGreen).Add(color.FgBlack).Add(color.Bold)
|
||||
if !runK(a, shellOpts{clear: true, banner: c.Sprintf(bannerFmt, fqn, co), args: args}) {
|
||||
a.Flash().Err(errors.New("Shell exec failed"))
|
||||
err = runK(a, shellOpts{clear: true, banner: c.Sprintf(bannerFmt, fqn, co), args: args})
|
||||
if err != nil {
|
||||
a.Flash().Errf("Shell exec failed: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -333,8 +403,8 @@ func resumeAttachIn(a *App, c model.Component, path, co string) {
|
|||
func attachIn(a *App, path, co string) {
|
||||
args := buildShellArgs("attach", path, co, a.Conn().Config().Flags().KubeConfig)
|
||||
c := color.New(color.BgGreen).Add(color.FgBlack).Add(color.Bold)
|
||||
if !runK(a, shellOpts{clear: true, banner: c.Sprintf(bannerFmt, path, co), args: args}) {
|
||||
a.Flash().Err(errors.New("Attach exec failed"))
|
||||
if err := runK(a, shellOpts{clear: true, banner: c.Sprintf(bannerFmt, path, co), args: args}); err != nil {
|
||||
a.Flash().Errf("Attach exec failed: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ func TestPodNew(t *testing.T) {
|
|||
|
||||
assert.Nil(t, po.Init(makeCtx()))
|
||||
assert.Equal(t, "Pods", po.Name())
|
||||
assert.Equal(t, 25, len(po.Hints()))
|
||||
assert.Equal(t, 26, len(po.Hints()))
|
||||
}
|
||||
|
||||
// Helpers...
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package view
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/derailed/k9s/internal"
|
||||
|
|
@ -49,6 +48,6 @@ func (s *ScreenDump) edit(app *App, model ui.Tabular, gvr, path string) {
|
|||
s.Stop()
|
||||
defer s.Start()
|
||||
if !edit(app, shellOpts{clear: true, args: []string{path}}) {
|
||||
app.Flash().Err(errors.New("Failed to launch editor"))
|
||||
app.Flash().Errf("Failed to launch editor")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ func (s *Service) showPods(a *App, _ ui.Tabular, gvr, path string) {
|
|||
|
||||
func (s *Service) checkSvc(svc *v1.Service) error {
|
||||
if svc.Spec.Type != "NodePort" && svc.Spec.Type != "LoadBalancer" {
|
||||
return errors.New("You must select a reachable service")
|
||||
return errors.New("you must select a reachable service")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -83,7 +83,7 @@ func (s *Service) getExternalPort(svc *v1.Service) (string, error) {
|
|||
// Grab the first port pair for now...
|
||||
tokens := strings.Split(pp[0], "►")
|
||||
if len(tokens) < 2 {
|
||||
return "", errors.New("No ports pair found")
|
||||
return "", errors.New("no ports pair found")
|
||||
}
|
||||
|
||||
return tokens[1], nil
|
||||
|
|
@ -142,7 +142,7 @@ func (s *Service) toggleBenchCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
// BOZO!! Refactor used by forwards.
|
||||
func (s *Service) runBenchmark(port string, cfg config.BenchConfig) error {
|
||||
if cfg.HTTP.Host == "" {
|
||||
return fmt.Errorf("Invalid benchmark host %q", cfg.HTTP.Host)
|
||||
return fmt.Errorf("invalid benchmark host %q", cfg.HTTP.Host)
|
||||
}
|
||||
|
||||
var err error
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package view
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
|
@ -413,8 +412,8 @@ func (x *Xray) editCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
if cfg := x.app.Conn().Config().Flags().KubeConfig; cfg != nil && *cfg != "" {
|
||||
args = append(args, "--kubeconfig", *cfg)
|
||||
}
|
||||
if !runK(x.app, shellOpts{args: append(args, n)}) {
|
||||
x.app.Flash().Err(errors.New("Edit exec failed"))
|
||||
if err := runK(x.app, shellOpts{args: append(args, n)}); err != nil {
|
||||
x.app.Flash().Errf("Edit exec failed: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ func (ff Forwarders) IsPodForwarded(fqn string) bool {
|
|||
|
||||
// IsContainerForwarded checks if pod has a forward.
|
||||
func (ff Forwarders) IsContainerForwarded(fqn, co string) bool {
|
||||
prefix := fqn+"|"+co
|
||||
prefix := fqn + "|" + co
|
||||
for k := range ff {
|
||||
if strings.HasPrefix(k, prefix) {
|
||||
return true
|
||||
|
|
@ -86,12 +86,11 @@ func (ff Forwarders) DeleteAll() {
|
|||
func (ff Forwarders) Kill(path string) int {
|
||||
var stats int
|
||||
for k, f := range ff {
|
||||
victim := k
|
||||
if victim == path {
|
||||
if strings.HasPrefix(k, path) {
|
||||
stats++
|
||||
log.Debug().Msgf("Stop + Delete port-forward %s", victim)
|
||||
log.Debug().Msgf("Stop + Delete port-forward %s", k)
|
||||
f.Stop()
|
||||
delete(ff, victim)
|
||||
delete(ff, k)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue