Skip to content

Commit d3027c8

Browse files
committed
K9s/release v0.32.4 (#2637)
* [Bug] fix #2605 * [Bug] fix #2604 * [Bug] fix #2592 * [Bug] fix #2608 * [Bug] Fix #2612 * Rel v0.32.4
1 parent c31a48f commit d3027c8

26 files changed

+214
-142
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ DATE ?= $(shell TZ=UTC date -j -f "%s" ${SOURCE_DATE_EPOCH} +"%Y-%m-%dT%H:
1111
else
1212
DATE ?= $(shell date -u -d @${SOURCE_DATE_EPOCH} +"%Y-%m-%dT%H:%M:%SZ")
1313
endif
14-
VERSION ?= v0.32.3
14+
VERSION ?= v0.32.4
1515
IMG_NAME := derailed/k9s
1616
IMAGE := ${IMG_NAME}:${VERSION}
1717

change_logs/release_v0.32.4.md

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/k9s.png" align="center" width="800" height="auto"/>
2+
3+
# Release v0.32.4
4+
5+
## Notes
6+
7+
Thank you to all that contributed with flushing out issues and enhancements for K9s!
8+
I'll try to mark some of these issues as fixed. But if you don't mind grab the latest rev
9+
and see if we're happier with some of the fixes!
10+
If you've filed an issue please help me verify and close.
11+
12+
Your support, kindness and awesome suggestions to make K9s better are, as ever, very much noted and appreciated!
13+
Also big thanks to all that have allocated their own time to help others on both slack and on this repo!!
14+
15+
As you may know, K9s is not pimped out by corps with deep pockets, thus if you feel K9s is helping your Kubernetes journey,
16+
please consider joining our [sponsorship program](https://github.com/sponsors/derailed) and/or make some noise on social! [@kitesurfer](https://twitter.com/kitesurfer)
17+
18+
On Slack? Please join us [K9slackers](https://join.slack.com/t/k9sers/shared_invite/enQtOTA5MDEyNzI5MTU0LWQ1ZGI3MzliYzZhZWEyNzYxYzA3NjE0YTk1YmFmNzViZjIyNzhkZGI0MmJjYzhlNjdlMGJhYzE2ZGU1NjkyNTM)
19+
20+
## Maintenance Release!
21+
22+
---
23+
24+
## ♫ Sounds Behind The Release ♭
25+
26+
Thinking of all you at KubeCon Paris!!
27+
May I suggest a nice glass of `cold Merlote` or other fine grape juices from my country?
28+
29+
* [Le Gorille - George Brassens](https://www.youtube.com/watch?v=KVfwvk_yVyA)
30+
* [Les Funerailles D'antan (Love this guy!) - George Brassens](https://www.youtube.com/watch?v=bwb5k4k2EMc)
31+
* [Poinconneur Des Lilas - Serge Gainsbourg](https://www.youtube.com/watch?v=eWkWCFzkOvU)
32+
* [Mon Legionaire (Yup! same guy??) - Serge Gainsbourg](https://www.youtube.com/watch?v=gl8gopryqWI)
33+
* [Les Cornichons - Nino Ferrer](https://www.youtube.com/watch?v=N7JSW4NhM8I)
34+
* [Paris s'eveille - Jacques Dutronc](https://www.youtube.com/watch?v=3WcCg6rm3uM)
35+
36+
---
37+
38+
## Videos Are In The Can!
39+
40+
Please dial [K9s Channel](https://www.youtube.com/channel/UC897uwPygni4QIjkPCpgjmw) for up coming content...
41+
42+
* [K9s v0.31.0 Configs+Sneak peek](https://youtu.be/X3444KfjguE)
43+
* [K9s v0.30.0 Sneak peek](https://youtu.be/mVBc1XneRJ4)
44+
* [Vulnerability Scans](https://youtu.be/ULkl0MsaidU)
45+
46+
---
47+
48+
## Resolved Issues
49+
50+
* [#2608](https://github.com/derailed/k9s/issues/2608) Make the sanitize feature easier to use
51+
* [#2605](https://github.com/derailed/k9s/issues/2605) Built-in shortcuts being overridden by plugins result in excessive logging
52+
* [#2604](https://github.com/derailed/k9s/issues/2604) Ability to mark a plugin as Dangerous/destructive
53+
* [#2592](https://github.com/derailed/k9s/issues/2592) "list access denied" when switching contexts within k9s since 0.32.0
54+
55+
---
56+
57+
## Contributed PRs
58+
59+
Please be sure to give `Big Thanks!` and `ATTA Girls/Boys!` to all the fine contributors for making K9s better for all of us!!
60+
61+
* [#2621](https://github.com/derailed/k9s/pull/2621) Fix snap build
62+
63+
---
64+
65+
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/imhotep_logo.png" width="32" height="auto"/> © 2024 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0)

internal/client/client.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -217,10 +217,10 @@ func (a *APIClient) ServerVersion() (*version.Info, error) {
217217
return info, nil
218218
}
219219

220-
func (a *APIClient) IsValidNamespace(n string) bool {
221-
ok, err := a.isValidNamespace(n)
220+
func (a *APIClient) IsValidNamespace(ns string) bool {
221+
ok, err := a.isValidNamespace(ns)
222222
if err != nil {
223-
log.Warn().Err(err).Msgf("namespace validation failed for: %q", n)
223+
log.Warn().Err(err).Msgf("namespace validation failed for: %q", ns)
224224
}
225225

226226
return ok

internal/config/data/context.go

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package data
55

66
import (
7+
"os"
78
"sync"
89

910
"github.com/derailed/k9s/internal/client"
@@ -70,6 +71,9 @@ func (c *Context) Validate(conn client.Connection, ks KubeSettings) {
7071
c.mx.Lock()
7172
defer c.mx.Unlock()
7273

74+
if a := os.Getenv(envPFAddress); a != "" {
75+
c.PortForwardAddress = a
76+
}
7377
if c.PortForwardAddress == "" {
7478
c.PortForwardAddress = defaultPFAddress()
7579
}

internal/config/data/ns.go

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ func NewActiveNamespace(n string) *Namespace {
3232
if n == client.BlankNamespace {
3333
n = client.DefaultNamespace
3434
}
35+
3536
return &Namespace{
3637
Active: n,
3738
Favorites: []string{client.DefaultNamespace},

internal/config/json/schemas/plugins.json

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"override": { "type": "boolean" },
1515
"description": { "type": "string" },
1616
"confirm": { "type": "boolean" },
17+
"dangerous": { "type": "boolean" },
1718
"scopes": {
1819
"type": "array",
1920
"items": { "type": "string" }

internal/config/plugin.go

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ type Plugin struct {
3636
Command string `yaml:"command"`
3737
Confirm bool `yaml:"confirm"`
3838
Background bool `yaml:"background"`
39+
Dangerous bool `yaml:"dangerous"`
3940
}
4041

4142
func (p Plugin) String() string {

internal/dao/pod.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -207,19 +207,19 @@ func (p *Pod) TailLogs(ctx context.Context, opts *LogOptions) ([]LogChan, error)
207207
return append(outs, tailLogs(ctx, p, opts)), nil
208208
}
209209
for _, co := range po.Spec.InitContainers {
210-
o := opts.Clone()
211-
o.Container = co.Name
212-
outs = append(outs, tailLogs(ctx, p, o))
210+
cfg := opts.Clone()
211+
cfg.Container = co.Name
212+
outs = append(outs, tailLogs(ctx, p, cfg))
213213
}
214214
for _, co := range po.Spec.Containers {
215-
o := opts.Clone()
216-
o.Container = co.Name
217-
outs = append(outs, tailLogs(ctx, p, o))
215+
cfg := opts.Clone()
216+
cfg.Container = co.Name
217+
outs = append(outs, tailLogs(ctx, p, cfg))
218218
}
219219
for _, co := range po.Spec.EphemeralContainers {
220-
o := opts.Clone()
221-
o.Container = co.Name
222-
outs = append(outs, tailLogs(ctx, p, o))
220+
cfg := opts.Clone()
221+
cfg.Container = co.Name
222+
outs = append(outs, tailLogs(ctx, p, cfg))
223223
}
224224

225225
return outs, nil

internal/render/sts.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,20 @@ func (s StatefulSet) Render(o interface{}, ns string, r *model1.Row) error {
5959
podContainerNames(sts.Spec.Template.Spec, true),
6060
podImageNames(sts.Spec.Template.Spec, true),
6161
mapToStr(sts.Labels),
62-
AsStatus(s.diagnose(sts.Status.Replicas, sts.Status.ReadyReplicas)),
62+
AsStatus(s.diagnose(sts.Spec.Replicas, sts.Status.Replicas, sts.Status.ReadyReplicas)),
6363
ToAge(sts.GetCreationTimestamp()),
6464
}
6565

6666
return nil
6767
}
6868

69-
func (StatefulSet) diagnose(d, r int32) error {
69+
func (StatefulSet) diagnose(w *int32, d, r int32) error {
7070
if d != r {
71-
return fmt.Errorf("desiring %d replicas got %d available", d, r)
71+
return fmt.Errorf("desired %d replicas got %d available", d, r)
7272
}
73+
if w != nil && *w != r {
74+
return fmt.Errorf("want %d replicas got %d available", *w, r)
75+
}
76+
7377
return nil
7478
}

internal/view/actions.go

+14-7
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func hotKeyActions(r Runner, aa *ui.KeyActions) error {
8080
errs = errors.Join(errs, fmt.Errorf("duplicate hotkey found for %q in %q", hk.ShortCut, k))
8181
continue
8282
}
83-
log.Info().Msgf("Action %q has been overridden by hotkey in %q", hk.ShortCut, k)
83+
log.Debug().Msgf("Action %q has been overridden by hotkey in %q", hk.ShortCut, k)
8484
}
8585

8686
command, err := r.EnvFn()().Substitute(hk.Command)
@@ -110,7 +110,6 @@ func gotoCmd(r Runner, cmd, path string, clearStack bool) ui.ActionHandler {
110110
}
111111

112112
func pluginActions(r Runner, aa *ui.KeyActions) error {
113-
pp := config.NewPlugins()
114113
aa.Range(func(k tcell.Key, a ui.KeyAction) {
115114
if a.Opts.Plugin {
116115
aa.Delete(k)
@@ -121,12 +120,16 @@ func pluginActions(r Runner, aa *ui.KeyActions) error {
121120
if err != nil {
122121
return err
123122
}
123+
pp := config.NewPlugins()
124124
if err := pp.Load(path); err != nil {
125125
return err
126126
}
127127

128-
var errs error
129-
aliases := r.Aliases()
128+
var (
129+
errs error
130+
aliases = r.Aliases()
131+
ro = r.App().Config.K9s.IsReadOnly()
132+
)
130133
for k, plugin := range pp.Plugins {
131134
if !inScope(plugin.Scopes, aliases) {
132135
continue
@@ -141,15 +144,19 @@ func pluginActions(r Runner, aa *ui.KeyActions) error {
141144
errs = errors.Join(errs, fmt.Errorf("duplicate plugin key found for %q in %q", plugin.ShortCut, k))
142145
continue
143146
}
144-
log.Info().Msgf("Action %q has been overridden by plugin in %q", plugin.ShortCut, k)
147+
log.Debug().Msgf("Action %q has been overridden by plugin in %q", plugin.ShortCut, k)
145148
}
146149

150+
if plugin.Dangerous && ro {
151+
continue
152+
}
147153
aa.Add(key, ui.NewKeyActionWithOpts(
148154
plugin.Description,
149155
pluginAction(r, plugin),
150156
ui.ActionOpts{
151-
Visible: true,
152-
Plugin: true,
157+
Visible: true,
158+
Plugin: true,
159+
Dangerous: plugin.Dangerous,
153160
},
154161
))
155162
}

internal/view/app.go

+3-18
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,6 @@ func (a *App) Init(version string, rate int) error {
111111
ns := a.Config.ActiveNamespace()
112112

113113
a.factory = watch.NewFactory(a.Conn())
114-
ok, err := a.isValidNS(ns)
115-
if !ok && err == nil {
116-
return fmt.Errorf("app-init - invalid namespace: %q", ns)
117-
}
118114
a.initFactory(ns)
119115

120116
a.clusterModel = model.NewClusterInfo(a.factory, a.version, a.Config.K9s)
@@ -438,18 +434,6 @@ func (a *App) switchNS(ns string) error {
438434
return a.factory.SetActiveNS(ns)
439435
}
440436

441-
func (a *App) isValidNS(ns string) (bool, error) {
442-
if ns == client.BlankNamespace || ns == client.NamespaceAll {
443-
return true, nil
444-
}
445-
446-
if !a.Conn().IsValidNamespace(ns) {
447-
return false, fmt.Errorf("invalid namespace: %q", ns)
448-
}
449-
450-
return true, nil
451-
}
452-
453437
func (a *App) switchContext(ci *cmd.Interpreter, force bool) error {
454438
name, ok := ci.HasContext()
455439
if !ok || a.Config.ActiveContextName() == name {
@@ -477,12 +461,13 @@ func (a *App) switchContext(ci *cmd.Interpreter, force bool) error {
477461
}
478462
ns := a.Config.ActiveNamespace()
479463
if !a.Conn().IsValidNamespace(ns) {
480-
a.Flash().Errf("Unable to validate namespace %q. Using %q namespace", ns, client.DefaultNamespace)
481-
ns = client.DefaultNamespace
464+
log.Warn().Msgf("Unable to validate namespace: %q. Using %q as active namespace", ns, ns)
482465
if err := a.Config.SetActiveNamespace(ns); err != nil {
483466
return err
484467
}
485468
}
469+
a.Flash().Errf("Using %q namespace", ns)
470+
486471
if err := a.Config.Save(true); err != nil {
487472
log.Error().Err(err).Msg("config save failed!")
488473
} else {

internal/view/details.go

+1
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ func (d *Details) StylesChanged(s *config.Styles) {
168168
// Update updates the view content.
169169
func (d *Details) Update(buff string) *Details {
170170
d.model.SetText(buff)
171+
171172
return d
172173
}
173174

internal/view/dp.go

+4-37
Original file line numberDiff line numberDiff line change
@@ -53,49 +53,16 @@ func (d *Deploy) logOptions(prev bool) (*dao.LogOptions, error) {
5353
if path == "" {
5454
return nil, errors.New("you must provide a selection")
5555
}
56-
57-
sts, err := d.dp(path)
56+
dp, err := d.getInstance(path)
5857
if err != nil {
5958
return nil, err
6059
}
6160

62-
cc := sts.Spec.Template.Spec.Containers
63-
var (
64-
co, dco string
65-
allCos bool
66-
)
67-
if c, ok := dao.GetDefaultContainer(sts.Spec.Template.ObjectMeta, sts.Spec.Template.Spec); ok {
68-
co, dco = c, c
69-
} else if len(cc) == 1 {
70-
co = cc[0].Name
71-
} else {
72-
dco, allCos = cc[0].Name, true
73-
}
74-
75-
cfg := d.App().Config.K9s.Logger
76-
opts := dao.LogOptions{
77-
Path: path,
78-
Container: co,
79-
Lines: int64(cfg.TailCount),
80-
SinceSeconds: cfg.SinceSeconds,
81-
SingleContainer: len(cc) == 1,
82-
AllContainers: allCos,
83-
ShowTimestamp: cfg.ShowTime,
84-
Previous: prev,
85-
}
86-
if co == "" {
87-
opts.AllContainers = true
88-
}
89-
opts.DefaultContainer = dco
90-
91-
return &opts, nil
61+
return podLogOptions(d.App(), path, prev, dp.ObjectMeta, dp.Spec.Template.Spec), nil
9262
}
9363

9464
func (d *Deploy) showPods(app *App, model ui.Tabular, gvr client.GVR, fqn string) {
95-
var ddp dao.Deployment
96-
ddp.Init(d.App().factory, d.GVR())
97-
98-
dp, err := ddp.GetInstance(fqn)
65+
dp, err := d.getInstance(fqn)
9966
if err != nil {
10067
app.Flash().Err(err)
10168
return
@@ -104,7 +71,7 @@ func (d *Deploy) showPods(app *App, model ui.Tabular, gvr client.GVR, fqn string
10471
showPodsFromSelector(app, fqn, dp.Spec.Selector)
10572
}
10673

107-
func (d *Deploy) dp(fqn string) (*appsv1.Deployment, error) {
74+
func (d *Deploy) getInstance(fqn string) (*appsv1.Deployment, error) {
10875
var dp dao.Deployment
10976
dp.Init(d.App().factory, d.GVR())
11077

0 commit comments

Comments
 (0)