K9s/rel v0.26.7 (#1816)

* update batch resource api and remove unused ingress render

* docs update: add rel notes + update release version
mine
Fernand Galiana 2022-10-18 09:01:20 -06:00 committed by GitHub
parent 66cbad82a3
commit 37569b8772
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 96 additions and 157 deletions

View File

@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- name: Install Go - name: Install Go
uses: actions/setup-go@v2 uses: actions/setup-go@v3.1.0
with: with:
go-version: 1.19 go-version: 1.19

View File

@ -13,7 +13,7 @@ RUN apk --no-cache add --update make libx11-dev git gcc libc-dev curl && make bu
# Build the final Docker image # Build the final Docker image
FROM alpine:3.16.2 FROM alpine:3.16.2
ARG KUBECTL_VERSION="v1.24.3" ARG KUBECTL_VERSION="v1.25.2"
COPY --from=build /k9s/execs/k9s /bin/k9s COPY --from=build /k9s/execs/k9s /bin/k9s
RUN apk add --update ca-certificates \ RUN apk add --update ca-certificates \

View File

@ -5,7 +5,7 @@ PACKAGE := github.com/derailed/$(NAME)
GIT_REV ?= $(shell git rev-parse --short HEAD) GIT_REV ?= $(shell git rev-parse --short HEAD)
SOURCE_DATE_EPOCH ?= $(shell date +%s) SOURCE_DATE_EPOCH ?= $(shell date +%s)
DATE ?= $(shell date -u -d @${SOURCE_DATE_EPOCH} +"%Y-%m-%dT%H:%M:%SZ") DATE ?= $(shell date -u -d @${SOURCE_DATE_EPOCH} +"%Y-%m-%dT%H:%M:%SZ")
VERSION ?= v0.26.6 VERSION ?= v0.26.7
IMG_NAME := derailed/k9s IMG_NAME := derailed/k9s
IMAGE := ${IMG_NAME}:${VERSION} IMAGE := ${IMG_NAME}:${VERSION}

View File

@ -87,7 +87,7 @@ K9s is available on Linux, macOS and Windows platforms.
```shell ```shell
# NOTE: The dev version will be in effect! # NOTE: The dev version will be in effect!
go install github.com/derailed/k9s go install github.com/derailed/k9s@latest
``` ```
* Via [Webi](https://webinstall.dev) for Linux and macOS * Via [Webi](https://webinstall.dev) for Linux and macOS
@ -359,7 +359,7 @@ K9s uses aliases to navigate most K8s resources.
- default - default
view: view:
active: dp active: dp
# The path to screen dump. Default: '%temp_dir%/k9s-screens-%username%' (k9s info) # The path to screen dump. Default: '%temp_dir%/k9s-screens-%username%' (k9s info)
screenDumpDir: /tmp screenDumpDir: /tmp
``` ```
@ -449,9 +449,9 @@ Entering the command mode and typing a resource name or alias, could be cumberso
As of v0.25.0, you can leverage the `FastForwards` feature to tell K9s how to default port-forwards. In situations where you are dealing with multiple containers or containers exposing multiple ports, it can be cumbersome to specify the desired port-forward from the dialog as in most cases, you already know which container/port tuple you desire. For these use cases, you can now annotate your manifests with the following annotations: As of v0.25.0, you can leverage the `FastForwards` feature to tell K9s how to default port-forwards. In situations where you are dealing with multiple containers or containers exposing multiple ports, it can be cumbersome to specify the desired port-forward from the dialog as in most cases, you already know which container/port tuple you desire. For these use cases, you can now annotate your manifests with the following annotations:
- `k9scli.io/auto-port-forwards` - `k9scli.io/auto-port-forwards`
activates one or more port-forwards directly bypassing the port-forward dialog all together. activates one or more port-forwards directly bypassing the port-forward dialog all together.
- `k9scli.io/port-forwards` - `k9scli.io/port-forwards`
pre-selects one or more port-forwards when launching the port-forward dialog. pre-selects one or more port-forwards when launching the port-forward dialog.
The annotation value takes on the shape `container-name::[local-port:]container-port` The annotation value takes on the shape `container-name::[local-port:]container-port`

View File

@ -0,0 +1,44 @@
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/k9s.png" align="center" width="800" height="auto"/>
# Release v0.26.7
## 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)
---
## Maintenance Release
---
## 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!!
* [Microsoft](https://github.com/microsoft)
* [Audun V. Nes](https://github.com/avnes)
* [Marco Aurelio Caldas Miranda](https://github.com/macmiranda)
* [Jon Waltom](https://github.com/jon-walton)
* [Eckl, Máté](https://github.com/ecklm)
* [Iguanasoft](https://github.com/iguanasoft)
---
## Resolved Issues
* [Issue #1805](https://github.com/derailed/k9s/issues/1805) CronJobs: allow sorting by LAST_SCHEDULE
## Contributed PRs (Thank you!!)
* [PR #1804](https://github.com/derailed/k9s/pull/1804) Allow multiple port forwards
* [PR #1797](https://github.com/derailed/k9s/pull/1797) README - use go install
* [PR #1793](https://github.com/derailed/k9s/pull/1793) Update CronJob version to v1
---
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/imhotep_logo.png" width="32" height="auto"/> © 2022 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0)

7
go.mod
View File

@ -26,9 +26,9 @@ require (
github.com/stretchr/testify v1.8.0 github.com/stretchr/testify v1.8.0
golang.org/x/text v0.4.0 golang.org/x/text v0.4.0
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
helm.sh/helm/v3 v3.10.0 helm.sh/helm/v3 v3.10.1
k8s.io/api v0.25.3 k8s.io/api v0.25.3
k8s.io/apiextensions-apiserver v0.25.1 k8s.io/apiextensions-apiserver v0.25.3
k8s.io/apimachinery v0.25.3 k8s.io/apimachinery v0.25.3
k8s.io/cli-runtime v0.25.3 k8s.io/cli-runtime v0.25.3
k8s.io/client-go v0.25.3 k8s.io/client-go v0.25.3
@ -145,6 +145,7 @@ require (
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/xlab/treeprint v1.1.0 // indirect github.com/xlab/treeprint v1.1.0 // indirect
go.etcd.io/etcd/api/v3 v3.5.4 // indirect
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
@ -159,7 +160,7 @@ require (
google.golang.org/protobuf v1.28.0 // indirect google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apiserver v0.25.1 // indirect k8s.io/apiserver v0.25.3 // indirect
k8s.io/component-base v0.25.3 // indirect k8s.io/component-base v0.25.3 // indirect
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect

14
go.sum
View File

@ -665,6 +665,8 @@ github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1
github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/api/v3 v3.5.4 h1:OHVyt3TopwtUQ2GKdd5wu3PmmipR4FTwCqoEjSyRdIc=
go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A=
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
@ -1140,8 +1142,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
helm.sh/helm/v3 v3.10.0 h1:y/MYONZ/bsld9kHwqgBX2uPggnUr5hahpjwt9/jrHlI= helm.sh/helm/v3 v3.10.1 h1:uTnNlYx8QcTSNA4ZJ50Llwife4CSohUY4ehumyVf2QE=
helm.sh/helm/v3 v3.10.0/go.mod h1:paPw0hO5KVfrCMbi1M8+P8xdfBri3IiJiVKATZsFR94= helm.sh/helm/v3 v3.10.1/go.mod h1:CXOcs02AYvrlPMWARNYNRgf2rNP7gLJQsi/Ubd4EDrI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 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-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@ -1151,12 +1153,12 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.25.3 h1:Q1v5UFfYe87vi5H7NU0p4RXC26PPMT8KOpr1TLQbCMQ= k8s.io/api v0.25.3 h1:Q1v5UFfYe87vi5H7NU0p4RXC26PPMT8KOpr1TLQbCMQ=
k8s.io/api v0.25.3/go.mod h1:o42gKscFrEVjHdQnyRenACrMtbuJsVdP+WVjqejfzmI= k8s.io/api v0.25.3/go.mod h1:o42gKscFrEVjHdQnyRenACrMtbuJsVdP+WVjqejfzmI=
k8s.io/apiextensions-apiserver v0.25.1 h1:HEIKlxj6oHaDwHgotEIX/Ld5K/RGuOFwN/TWMiQ5s5s= k8s.io/apiextensions-apiserver v0.25.3 h1:bfI4KS31w2f9WM1KLGwnwuVlW3RSRPuIsfNF/3HzR0k=
k8s.io/apiextensions-apiserver v0.25.1/go.mod h1:67sgnMs2yIO2iV4DpCdS91vlP+pdnVIsG/mz60qRn44= k8s.io/apiextensions-apiserver v0.25.3/go.mod h1:ZJqwpCkxIx9itilmZek7JgfUAM0dnTsA48I4krPqRmo=
k8s.io/apimachinery v0.25.3 h1:7o9ium4uyUOM76t6aunP0nZuex7gDf8VGwkR5RcJnQc= k8s.io/apimachinery v0.25.3 h1:7o9ium4uyUOM76t6aunP0nZuex7gDf8VGwkR5RcJnQc=
k8s.io/apimachinery v0.25.3/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo= k8s.io/apimachinery v0.25.3/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo=
k8s.io/apiserver v0.25.1 h1:A3gnoQL6lhqRiwWN6f2DGBGdCb+7brCSTrW3klR9Xwc= k8s.io/apiserver v0.25.3 h1:m7+xGuG5+KYAnEsqaFtDyWMkmMMEOFYlu+NlWv5qSBI=
k8s.io/apiserver v0.25.1/go.mod h1:IB1EhM28U3cCrV+VNC06p1/YSZMCNYiH+P5sI5yLaZY= k8s.io/apiserver v0.25.3/go.mod h1:9bT47iM2fzRuhICJpM/RcQR9sqDDfZ7Yw60h0p3JW08=
k8s.io/cli-runtime v0.25.3 h1:Zs7P7l7db/5J+KDePOVtDlArAa9pZXaDinGWGZl0aM8= k8s.io/cli-runtime v0.25.3 h1:Zs7P7l7db/5J+KDePOVtDlArAa9pZXaDinGWGZl0aM8=
k8s.io/cli-runtime v0.25.3/go.mod h1:InHHsjkyW5hQsILJGpGjeruiDZT/R0OkROQgD6GzxO4= k8s.io/cli-runtime v0.25.3/go.mod h1:InHHsjkyW5hQsILJGpGjeruiDZT/R0OkROQgD6GzxO4=
k8s.io/client-go v0.25.3 h1:oB4Dyl8d6UbfDHD8Bv8evKylzs3BXzzufLiO27xuPs0= k8s.io/client-go v0.25.3 h1:oB4Dyl8d6UbfDHD8Bv8evKylzs3BXzzufLiO27xuPs0=

View File

@ -20,7 +20,7 @@ import (
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
metricsapi "k8s.io/metrics/pkg/apis/metrics" metricsapi "k8s.io/metrics/pkg/apis/metrics"
versioned "k8s.io/metrics/pkg/client/clientset/versioned" "k8s.io/metrics/pkg/client/clientset/versioned"
) )
const ( const (
@ -188,8 +188,8 @@ func (a *APIClient) CurrentNamespaceName() (string, error) {
// ServerVersion returns the current server version info. // ServerVersion returns the current server version info.
func (a *APIClient) ServerVersion() (*version.Info, error) { func (a *APIClient) ServerVersion() (*version.Info, error) {
if v, ok := a.cache.Get(serverVersion); ok { if v, ok := a.cache.Get(serverVersion); ok {
if version, ok := v.(*version.Info); ok { if vi, ok := v.(*version.Info); ok {
return version, nil return vi, nil
} }
} }
dial, err := a.CachedDiscovery() dial, err := a.CachedDiscovery()
@ -242,7 +242,7 @@ func (a *APIClient) CheckConnectivity() bool {
} }
}() }()
// Need to reload to pickup any kubeconfig changes. // Need reload to pick up any kubeconfig changes.
cfg, err := NewConfig(a.config.flags).RESTConfig() cfg, err := NewConfig(a.config.flags).RESTConfig()
if err != nil { if err != nil {
log.Error().Err(err).Msgf("restConfig load failed") log.Error().Err(err).Msgf("restConfig load failed")
@ -281,10 +281,10 @@ func (a *APIClient) HasMetrics() bool {
return err == nil return err == nil
} }
// LogDial returns a handle to api server for logs. // DialLogs returns a handle to api server for logs.
func (a *APIClient) DialLogs() (kubernetes.Interface, error) { func (a *APIClient) DialLogs() (kubernetes.Interface, error) {
if !a.connOK { if !a.connOK {
return nil, errors.New("No connection to dial") return nil, errors.New("no connection to dial")
} }
if a.logClient != nil { if a.logClient != nil {
return a.logClient, nil return a.logClient, nil
@ -305,7 +305,7 @@ func (a *APIClient) DialLogs() (kubernetes.Interface, error) {
// Dial returns a handle to api server or die. // Dial returns a handle to api server or die.
func (a *APIClient) Dial() (kubernetes.Interface, error) { func (a *APIClient) Dial() (kubernetes.Interface, error) {
if !a.connOK { if !a.connOK {
return nil, errors.New("No connection to dial") return nil, errors.New("no connection to dial")
} }
if a.client != nil { if a.client != nil {
return a.client, nil return a.client, nil
@ -333,7 +333,7 @@ func (a *APIClient) CachedDiscovery() (*disk.CachedDiscoveryClient, error) {
defer a.mx.Unlock() defer a.mx.Unlock()
if !a.connOK { if !a.connOK {
return nil, errors.New("No connection to cached dial") return nil, errors.New("no connection to cached dial")
} }
if a.cachedClient != nil { if a.cachedClient != nil {
@ -406,7 +406,7 @@ func (a *APIClient) SwitchContext(name string) error {
a.mx.Unlock() a.mx.Unlock()
if !a.CheckConnectivity() { if !a.CheckConnectivity() {
return fmt.Errorf("Unable to connect to context %q", name) return fmt.Errorf("unable to connect to context %q", name)
} }
return nil return nil
@ -465,9 +465,9 @@ func (a *APIClient) supportsMetricsResources() error {
} }
func checkMetricsVersion(grp metav1.APIGroup) bool { func checkMetricsVersion(grp metav1.APIGroup) bool {
for _, version := range grp.Versions { for _, v := range grp.Versions {
for _, supportedVersion := range supportedMetricsAPIVersions { for _, supportedVersion := range supportedMetricsAPIVersions {
if version.Version == supportedVersion { if v.Version == supportedVersion {
return true return true
} }
} }

View File

@ -40,12 +40,12 @@ var (
func scanners() map[string]RefScanner { func scanners() map[string]RefScanner {
return map[string]RefScanner{ return map[string]RefScanner{
"apps/v1/deployments": &Deployment{}, "apps/v1/deployments": &Deployment{},
"apps/v1/statefulsets": &StatefulSet{}, "apps/v1/statefulsets": &StatefulSet{},
"apps/v1/daemonsets": &DaemonSet{}, "apps/v1/daemonsets": &DaemonSet{},
"batch/v1/jobs": &Job{}, "batch/v1/jobs": &Job{},
"batch/v1beta1/cronjobs": &CronJob{}, "batch/v1/cronjobs": &CronJob{},
"v1/pods": &Pod{}, "v1/pods": &Pod{},
} }
} }

View File

@ -62,7 +62,7 @@ func (c *CronJob) Run(path string) error {
Labels: cj.Spec.JobTemplate.Labels, Labels: cj.Spec.JobTemplate.Labels,
OwnerReferences: []metav1.OwnerReference{ OwnerReferences: []metav1.OwnerReference{
{ {
APIVersion: c.gvr.G() + "/" + c.gvr.V(), APIVersion: c.gvr.GV().String(),
Kind: "CronJob", Kind: "CronJob",
BlockOwnerDeletion: &true, BlockOwnerDeletion: &true,
Name: cj.Name, Name: cj.Name,

View File

@ -117,7 +117,9 @@ func (h *Helm) Delete(_ context.Context, path string, _ *metav1.DeletionPropagat
if err != nil { if err != nil {
return err return err
} }
res, err := action.NewUninstall(cfg).Run(n) u := action.NewUninstall(cfg)
u.KeepHistory = true
res, err := u.Run(n)
if err != nil { if err != nil {
return err return err
} }

View File

@ -1,98 +0,0 @@
package render
import (
"fmt"
"strings"
"github.com/derailed/k9s/internal/client"
v1 "k8s.io/api/core/v1"
netv1 "k8s.io/api/networking/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
)
// Ingress renders a K8s Ingress to screen.
type Ingress struct{}
// ColorerFunc colors a resource row.
func (Ingress) ColorerFunc() ColorerFunc {
return DefaultColorer
}
// Header returns a header row.
func (Ingress) Header(ns string) Header {
return Header{
HeaderColumn{Name: "NAMESPACE"},
HeaderColumn{Name: "NAME"},
HeaderColumn{Name: "CLASS"},
HeaderColumn{Name: "HOSTS"},
HeaderColumn{Name: "ADDRESS"},
HeaderColumn{Name: "PORTS"},
HeaderColumn{Name: "LABELS", Wide: true},
HeaderColumn{Name: "AGE", Time: true},
}
}
// Render renders a K8s resource to screen.
func (i Ingress) Render(o interface{}, ns string, r *Row) error {
raw, ok := o.(*unstructured.Unstructured)
if !ok {
return fmt.Errorf("Expected Ingress, but got %T", o)
}
var ing netv1.Ingress
err := runtime.DefaultUnstructuredConverter.FromUnstructured(raw.Object, &ing)
if err != nil {
return err
}
r.ID = client.MetaFQN(ing.ObjectMeta)
r.Fields = Fields{
ing.Namespace,
ing.Name,
strpToStr(ing.Spec.IngressClassName),
toHosts(ing.Spec.Rules),
toAddress(ing.Status.LoadBalancer),
toTLSPorts(ing.Spec.TLS),
mapToStr(ing.Labels),
toAge(ing.GetCreationTimestamp()),
}
return nil
}
// ----------------------------------------------------------------------------
// Helpers...
func toAddress(lbs v1.LoadBalancerStatus) string {
ings := lbs.Ingress
res := make([]string, 0, len(ings))
for _, lb := range ings {
if len(lb.IP) > 0 {
res = append(res, lb.IP)
} else if len(lb.Hostname) != 0 {
res = append(res, lb.Hostname)
}
}
return strings.Join(res, ",")
}
func toTLSPorts(tls []netv1.IngressTLS) string {
if len(tls) != 0 {
return "80, 443"
}
return "80"
}
func toHosts(rr []netv1.IngressRule) string {
hh := make([]string, 0, len(rr))
for _, r := range rr {
if r.Host == "" {
r.Host = "*"
}
hh = append(hh, r.Host)
}
return strings.Join(hh, ",")
}

View File

@ -1,17 +0,0 @@
package render_test
import (
"testing"
"github.com/derailed/k9s/internal/render"
"github.com/stretchr/testify/assert"
)
func TestIngressRender(t *testing.T) {
c := render.Ingress{}
r := render.NewRow(6)
c.Render(load(t, "ing"), "", &r)
assert.Equal(t, "default/test-ingress", r.ID)
assert.Equal(t, render.Fields{"default", "test-ingress", "<none>", "*", "", "80", "role=ingress"}, r.Fields[:7])
}

View File

@ -19,7 +19,11 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
) )
const suspendDialogKey = "suspend" const (
suspendDialogKey = "suspend"
lastScheduledCol = "LAST_SCHEDULE"
defaultSuspendStatus = "true"
)
// CronJob represents a cronjob viewer. // CronJob represents a cronjob viewer.
type CronJob struct { type CronJob struct {
@ -66,8 +70,9 @@ func jobCtx(path, uid string) ContextFunc {
func (c *CronJob) bindKeys(aa ui.KeyActions) { func (c *CronJob) bindKeys(aa ui.KeyActions) {
aa.Add(ui.KeyActions{ aa.Add(ui.KeyActions{
ui.KeyT: ui.NewKeyAction("Trigger", c.triggerCmd, true), ui.KeyT: ui.NewKeyAction("Trigger", c.triggerCmd, true),
ui.KeyS: ui.NewKeyAction("Suspend/Resume", c.toggleSuspendCmd, true), ui.KeyS: ui.NewKeyAction("Suspend/Resume", c.toggleSuspendCmd, true),
ui.KeyShiftL: ui.NewKeyAction("Sort LastScheduled", c.GetTable().SortColCmd(lastScheduledCol, true), false),
}) })
} }
@ -119,7 +124,7 @@ func (c *CronJob) showSuspendDialog(sel string) {
c.App().Flash().Errf("Unable to assert current status") c.App().Flash().Errf("Unable to assert current status")
return return
} }
suspended := strings.TrimSpace(cell.Text) == "True" suspended := strings.TrimSpace(cell.Text) == defaultSuspendStatus
title := "Suspend" title := "Suspend"
if suspended { if suspended {
title = "Resume" title = "Resume"
@ -136,9 +141,9 @@ func (c *CronJob) showSuspendDialog(sel string) {
func (c *CronJob) makeSuspendForm(sel string, suspend bool) *tview.Form { func (c *CronJob) makeSuspendForm(sel string, suspend bool) *tview.Form {
f := c.makeStyledForm() f := c.makeStyledForm()
action := "suspend" action := "suspended"
if !suspend { if !suspend {
action = "resume" action = "resumed"
} }
f.AddButton("Cancel", func() { f.AddButton("Cancel", func() {
@ -153,7 +158,7 @@ func (c *CronJob) makeSuspendForm(sel string, suspend bool) *tview.Form {
log.Error().Err(err).Msgf("CronJob %s %s failed", sel, action) log.Error().Err(err).Msgf("CronJob %s %s failed", sel, action)
c.App().Flash().Err(err) c.App().Flash().Err(err)
} else { } else {
c.App().Flash().Infof("CronJob %s %s successfully", sel, action) c.App().Flash().Infof("CronJob %s %s successfully!", sel, action)
} }
}) })