Rel v0.50.12 (#3572)
* fix #3570 - broken display when no resources * fix #3547 - surface error * fix #3562 - rbac del ns * rel notesmine
parent
ab839ed11e
commit
09c1c07950
2
Makefile
2
Makefile
|
|
@ -1,5 +1,5 @@
|
||||||
NAME := k9s
|
NAME := k9s
|
||||||
VERSION ?= v0.50.11
|
VERSION ?= v0.50.12
|
||||||
PACKAGE := github.com/derailed/$(NAME)
|
PACKAGE := github.com/derailed/$(NAME)
|
||||||
OUTPUT_BIN ?= execs/${NAME}
|
OUTPUT_BIN ?= execs/${NAME}
|
||||||
GO_FLAGS ?=
|
GO_FLAGS ?=
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/k9s.png" align="center" width="800" height="auto"/>
|
||||||
|
|
||||||
|
# Release v0.50.12
|
||||||
|
|
||||||
|
## 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/zt-3360a389v-ElLHrb0Dp1kAXqYUItSAFA)
|
||||||
|
|
||||||
|
## Maintenance Release!
|
||||||
|
|
||||||
|
## Resolved Issues
|
||||||
|
|
||||||
|
* [#3570](https://github.com/derailed/k9s/issues/3570) 0.50.11 could not display any resources
|
||||||
|
* [#3562](https://github.com/derailed/k9s/issues/3562) Can't delete namespace
|
||||||
|
* [#3547](https://github.com/derailed/k9s/issues/3547) Error message from admission controller
|
||||||
|
|
||||||
|
---
|
||||||
|
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/imhotep_logo.png" width="32" height="auto"/> © 2025 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0)#
|
||||||
|
|
@ -184,7 +184,7 @@ func (a *APIClient) CanI(ns string, gvr *GVR, name string, verbs []string) (auth
|
||||||
slogs.Verb, verbs,
|
slogs.Verb, verbs,
|
||||||
)
|
)
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
clog.Debug("[CAN] reps",
|
clog.Debug("[CAN] response",
|
||||||
slogs.AuthStatus, resp.Status.Allowed,
|
slogs.AuthStatus, resp.Status.Allowed,
|
||||||
slogs.AuthReason, resp.Status.Reason,
|
slogs.AuthReason, resp.Status.Reason,
|
||||||
)
|
)
|
||||||
|
|
@ -196,7 +196,7 @@ func (a *APIClient) CanI(ns string, gvr *GVR, name string, verbs []string) (auth
|
||||||
}
|
}
|
||||||
if !resp.Status.Allowed {
|
if !resp.Status.Allowed {
|
||||||
a.cache.Add(key, false, cacheExpiry)
|
a.cache.Add(key, false, cacheExpiry)
|
||||||
return auth, fmt.Errorf("`%s access denied for user on %q:%s", v, ns, gvr)
|
return auth, fmt.Errorf("(%s) access denied for user on resource %q:%s in namespace %q", v, name, gvr, ns)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auth = true
|
auth = true
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// DefaultFlashDelay sets the flash clear delay.
|
// DefaultFlashDelay sets the flash clear delay.
|
||||||
DefaultFlashDelay = 3 * time.Second
|
DefaultFlashDelay = 6 * time.Second
|
||||||
|
|
||||||
// FlashInfo represents an info message.
|
// FlashInfo represents an info message.
|
||||||
FlashInfo FlashLevel = iota
|
FlashInfo FlashLevel = iota
|
||||||
|
|
|
||||||
|
|
@ -302,8 +302,8 @@ func (b *Browser) TableNoData(mdata *model1.TableData) {
|
||||||
if !b.app.ConOK() || cancel == nil || !b.app.IsRunning() {
|
if !b.app.ConOK() || cancel == nil || !b.app.IsRunning() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Skip warning on first view or if table data is empty (likely during initialization)
|
// Skip warning on first view (likely during initialization)
|
||||||
if b.firstView.Load() == 0 || mdata.Empty() {
|
if b.firstView.Load() == 0 || mdata.HeaderCount() == 0 {
|
||||||
b.firstView.Add(1)
|
b.firstView.Add(1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -316,7 +316,7 @@ func (b *Browser) TableNoData(mdata *model1.TableData) {
|
||||||
b.setUpdating(true)
|
b.setUpdating(true)
|
||||||
defer b.setUpdating(false)
|
defer b.setUpdating(false)
|
||||||
if b.GetColumnCount() == 0 {
|
if b.GetColumnCount() == 0 {
|
||||||
b.app.Flash().Warnf("No resources found for %s in namespace %s", b.GVR(), client.PrintNamespace(b.GetNamespace()))
|
b.app.Flash().Warnf("No resources found for %s in %q namespace", b.GVR(), client.PrintNamespace(b.GetNamespace()))
|
||||||
}
|
}
|
||||||
b.refreshActions()
|
b.refreshActions()
|
||||||
b.UpdateUI(cdata, mdata)
|
b.UpdateUI(cdata, mdata)
|
||||||
|
|
|
||||||
|
|
@ -164,9 +164,21 @@ func (c *Container) shellCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
return evt
|
return evt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
c.Stop()
|
c.Stop()
|
||||||
defer c.Start()
|
defer func() {
|
||||||
shellIn(c.App(), c.GetTable().Path, path)
|
c.Start()
|
||||||
|
if err != nil {
|
||||||
|
c.App().QueueUpdate(func() {
|
||||||
|
if err != nil {
|
||||||
|
c.App().Flash().Errf("Shell exec failed: %s", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
c.App().Flash().Err(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
err = shellIn(c.App(), c.GetTable().Path, path)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -587,7 +587,7 @@ func pipe(_ context.Context, opts *shellOpts, statusChan chan<- string, w, e *by
|
||||||
close(statusChan)
|
close(statusChan)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("command failed. Check logs: %w", err)
|
err = fmt.Errorf("command failed. Check k9s logs: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -393,28 +393,33 @@ func containerShellIn(a *App, comp model.Component, path, co string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func resumeShellIn(a *App, c model.Component, path, co string) {
|
func resumeShellIn(a *App, c model.Component, path, co string) {
|
||||||
|
var err error
|
||||||
c.Stop()
|
c.Stop()
|
||||||
defer c.Start()
|
defer func() {
|
||||||
|
c.Start()
|
||||||
|
a.QueueUpdate(func() {
|
||||||
|
if err != nil {
|
||||||
|
a.Flash().Errf("Shell exec failed: %s", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}()
|
||||||
|
|
||||||
shellIn(a, path, co)
|
err = shellIn(a, path, co)
|
||||||
}
|
}
|
||||||
|
|
||||||
func shellIn(a *App, fqn, co string) {
|
func shellIn(a *App, fqn, co string) error {
|
||||||
platform, err := getPodOS(a.factory, fqn)
|
platform, err := getPodOS(a.factory, fqn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Warn("OS detect failed", slogs.Error, err)
|
return err
|
||||||
}
|
}
|
||||||
args := computeShellArgs(fqn, co, a.Conn().Config().Flags(), platform)
|
|
||||||
|
|
||||||
|
args := computeShellArgs(fqn, co, a.Conn().Config().Flags(), platform)
|
||||||
c := color.New(color.BgGreen).Add(color.FgBlack).Add(color.Bold)
|
c := color.New(color.BgGreen).Add(color.FgBlack).Add(color.Bold)
|
||||||
err = runK(a, &shellOpts{
|
return runK(a, &shellOpts{
|
||||||
clear: true,
|
clear: true,
|
||||||
banner: c.Sprintf(bannerFmt, fqn, co),
|
banner: c.Sprintf(bannerFmt, fqn, co),
|
||||||
args: args},
|
args: args},
|
||||||
)
|
)
|
||||||
if err != nil {
|
|
||||||
a.Flash().Errf("Shell exec failed: %s", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func containerAttachIn(a *App, comp model.Component, path, co string) error {
|
func containerAttachIn(a *App, comp model.Component, path, co string) error {
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,11 @@ func (f *Factory) isClusterWide() bool {
|
||||||
|
|
||||||
// CanForResource return an informer is user has access.
|
// CanForResource return an informer is user has access.
|
||||||
func (f *Factory) CanForResource(ns string, gvr *client.GVR, verbs []string) (informers.GenericInformer, error) {
|
func (f *Factory) CanForResource(ns string, gvr *client.GVR, verbs []string) (informers.GenericInformer, error) {
|
||||||
auth, err := f.Client().CanI(ns, gvr, "", verbs)
|
var resName string
|
||||||
|
if gvr == client.NsGVR {
|
||||||
|
resName = ns
|
||||||
|
}
|
||||||
|
auth, err := f.Client().CanI(ns, gvr, resName, verbs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
name: k9s
|
name: k9s
|
||||||
base: core22
|
base: core22
|
||||||
version: 'v0.50.11'
|
version: 'v0.50.12'
|
||||||
summary: K9s is a CLI to view and manage your Kubernetes clusters.
|
summary: K9s is a CLI to view and manage your Kubernetes clusters.
|
||||||
description: |
|
description: |
|
||||||
K9s is a CLI to view and manage your Kubernetes clusters. By leveraging a terminal UI, you can easily traverse Kubernetes resources and view the state of your clusters in a single powerful session.
|
K9s is a CLI to view and manage your Kubernetes clusters. By leveraging a terminal UI, you can easily traverse Kubernetes resources and view the state of your clusters in a single powerful session.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue