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
steps:
- name: Install Go
uses: actions/setup-go@v2
uses: actions/setup-go@v3.1.0
with:
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
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
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)
SOURCE_DATE_EPOCH ?= $(shell date +%s)
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
IMAGE := ${IMG_NAME}:${VERSION}

View File

@ -87,7 +87,7 @@ K9s is available on Linux, macOS and Windows platforms.
```shell
# 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

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
golang.org/x/text v0.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/apiextensions-apiserver v0.25.1
k8s.io/apiextensions-apiserver v0.25.3
k8s.io/apimachinery v0.25.3
k8s.io/cli-runtime 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/gojsonschema v1.2.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
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
@ -159,7 +160,7 @@ require (
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/inf.v0 v0.9.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/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // 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/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.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/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
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=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
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.0/go.mod h1:paPw0hO5KVfrCMbi1M8+P8xdfBri3IiJiVKATZsFR94=
helm.sh/helm/v3 v3.10.1 h1:uTnNlYx8QcTSNA4ZJ50Llwife4CSohUY4ehumyVf2QE=
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-20190106161140-3f1c8253044a/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=
k8s.io/api v0.25.3 h1:Q1v5UFfYe87vi5H7NU0p4RXC26PPMT8KOpr1TLQbCMQ=
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.1/go.mod h1:67sgnMs2yIO2iV4DpCdS91vlP+pdnVIsG/mz60qRn44=
k8s.io/apiextensions-apiserver v0.25.3 h1:bfI4KS31w2f9WM1KLGwnwuVlW3RSRPuIsfNF/3HzR0k=
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/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo=
k8s.io/apiserver v0.25.1 h1:A3gnoQL6lhqRiwWN6f2DGBGdCb+7brCSTrW3klR9Xwc=
k8s.io/apiserver v0.25.1/go.mod h1:IB1EhM28U3cCrV+VNC06p1/YSZMCNYiH+P5sI5yLaZY=
k8s.io/apiserver v0.25.3 h1:m7+xGuG5+KYAnEsqaFtDyWMkmMMEOFYlu+NlWv5qSBI=
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/go.mod h1:InHHsjkyW5hQsILJGpGjeruiDZT/R0OkROQgD6GzxO4=
k8s.io/client-go v0.25.3 h1:oB4Dyl8d6UbfDHD8Bv8evKylzs3BXzzufLiO27xuPs0=

View File

@ -20,7 +20,7 @@ import (
"k8s.io/client-go/kubernetes"
restclient "k8s.io/client-go/rest"
metricsapi "k8s.io/metrics/pkg/apis/metrics"
versioned "k8s.io/metrics/pkg/client/clientset/versioned"
"k8s.io/metrics/pkg/client/clientset/versioned"
)
const (
@ -188,8 +188,8 @@ func (a *APIClient) CurrentNamespaceName() (string, error) {
// ServerVersion returns the current server version info.
func (a *APIClient) ServerVersion() (*version.Info, error) {
if v, ok := a.cache.Get(serverVersion); ok {
if version, ok := v.(*version.Info); ok {
return version, nil
if vi, ok := v.(*version.Info); ok {
return vi, nil
}
}
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()
if err != nil {
log.Error().Err(err).Msgf("restConfig load failed")
@ -281,10 +281,10 @@ func (a *APIClient) HasMetrics() bool {
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) {
if !a.connOK {
return nil, errors.New("No connection to dial")
return nil, errors.New("no connection to dial")
}
if 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.
func (a *APIClient) Dial() (kubernetes.Interface, error) {
if !a.connOK {
return nil, errors.New("No connection to dial")
return nil, errors.New("no connection to dial")
}
if a.client != nil {
return a.client, nil
@ -333,7 +333,7 @@ func (a *APIClient) CachedDiscovery() (*disk.CachedDiscoveryClient, error) {
defer a.mx.Unlock()
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 {
@ -406,7 +406,7 @@ func (a *APIClient) SwitchContext(name string) error {
a.mx.Unlock()
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
@ -465,9 +465,9 @@ func (a *APIClient) supportsMetricsResources() error {
}
func checkMetricsVersion(grp metav1.APIGroup) bool {
for _, version := range grp.Versions {
for _, v := range grp.Versions {
for _, supportedVersion := range supportedMetricsAPIVersions {
if version.Version == supportedVersion {
if v.Version == supportedVersion {
return true
}
}

View File

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

View File

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

View File

@ -117,7 +117,9 @@ func (h *Helm) Delete(_ context.Context, path string, _ *metav1.DeletionPropagat
if err != nil {
return err
}
res, err := action.NewUninstall(cfg).Run(n)
u := action.NewUninstall(cfg)
u.KeepHistory = true
res, err := u.Run(n)
if err != nil {
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"
)
const suspendDialogKey = "suspend"
const (
suspendDialogKey = "suspend"
lastScheduledCol = "LAST_SCHEDULE"
defaultSuspendStatus = "true"
)
// CronJob represents a cronjob viewer.
type CronJob struct {
@ -68,6 +72,7 @@ func (c *CronJob) bindKeys(aa ui.KeyActions) {
aa.Add(ui.KeyActions{
ui.KeyT: ui.NewKeyAction("Trigger", c.triggerCmd, 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")
return
}
suspended := strings.TrimSpace(cell.Text) == "True"
suspended := strings.TrimSpace(cell.Text) == defaultSuspendStatus
title := "Suspend"
if suspended {
title = "Resume"
@ -136,9 +141,9 @@ func (c *CronJob) showSuspendDialog(sel string) {
func (c *CronJob) makeSuspendForm(sel string, suspend bool) *tview.Form {
f := c.makeStyledForm()
action := "suspend"
action := "suspended"
if !suspend {
action = "resume"
action = "resumed"
}
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)
c.App().Flash().Err(err)
} else {
c.App().Flash().Infof("CronJob %s %s successfully", sel, action)
c.App().Flash().Infof("CronJob %s %s successfully!", sel, action)
}
})