Skip to content

Commit

Permalink
K9s/release v0.31.9 (#2543)
Browse files Browse the repository at this point in the history
* [Bug] fix #2535

* [Bug] fix #2532

* [Bug] fix #2536

* [Bug] fix #2533

* [Bug] fix #2538

* [Maint] cleaning up

* Release notes
  • Loading branch information
derailed authored Feb 16, 2024
1 parent 207d056 commit f2f4077
Show file tree
Hide file tree
Showing 33 changed files with 376 additions and 241 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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.31.8
VERSION ?= v0.31.9
IMG_NAME := derailed/k9s
IMAGE := ${IMG_NAME}:${VERSION}

Expand Down
98 changes: 98 additions & 0 deletions change_logs/release_v0.31.9.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/k9s.png" align="center" width="800" height="auto"/>

# Release v0.31.9

## 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!

```text
S .-'-.
o __| F `\
S `-,-`--._ `\
[] .->' X `|-'
`=/ (__/_ /
\_, ` _)
`----; |
```

⛔️ WE HAVE A PIPER DOWN! I REPEAT PIPER IS DOWN!! ⛔️

Popeye is undergoing heavy surgery at the moment so I had to break the bridge.
If you dig Popeye please run the binary separately for the time being.
I'll post another message here once the spinach formula upgrade is successful!

Also please make sure to add the gory details to issues ie relevant configs, debug logs, etc...
Comments like: `same here!` or `me to!` doesn't really cut it for us to zero in ;(

Everyone has slightly different settings/platforms so every little bits of info helps with the resolves even if seemingly irrelevant.

Thank you all for pitching in and helping flesh out issues!!

---

## Videos Are In The Can!

Please dial [K9s Channel](https://www.youtube.com/channel/UC897uwPygni4QIjkPCpgjmw) for up coming content...

* [K9s v0.31.0 Configs+Sneak peek](https://youtu.be/X3444KfjguE)
* [K9s v0.30.0 Sneak peek](https://youtu.be/mVBc1XneRJ4)
* [Vulnerability Scans](https://youtu.be/ULkl0MsaidU)

---

## ♫ Sounds Behind The Release ♭

Ushered or Taylored out?

* [Rough God Goes Riding - Van Morrison](https://www.youtube.com/watch?v=-kGrwRlJxcM)
* [Walk On - John Hiatt](https://www.youtube.com/watch?v=YVdMyeTQCkw)
* [On The Beach - Neil Young](https://www.youtube.com/watch?v=KBVde75e4sU)

---

## 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!!

* [Francis Lalonde](https://github.com/f-lalonde)
* [e-conomic a/s](https://github.com/e-conomic)

> Sponsorship cancellations since the last release: **2!** 🥹
---

## Resolved Issues

* [#2540](https://github.com/derailed/k9s/issues/2540) Option --write not functional
* [#2538](https://github.com/derailed/k9s/issues/2538) Opening screen dumps (sd) in K9s results in Failed to launch editor error message
* [#2536](https://github.com/derailed/k9s/issues/2536) Recent namespaces are lost when changing context
* [#2535](https://github.com/derailed/k9s/issues/2535) Namespaced configmap edit fails for user with RoleBinding to a role that allows it
* [#2532](https://github.com/derailed/k9s/issues/2532) Sporadic crashes (Maybe??)

---

## Contributed PRs

Please be sure to give `Big Thanks!` and `ATTA Girls/Boys!` to all the fine contributors for making K9s better for all of us!!

* [#2541](https://github.com/derailed/k9s/pull/2541) Add Rose Pine moon and dawn variants to skins
* [#2531](https://github.com/derailed/k9s/pull/2531) fix the --write flag
* [#2516](https://github.com/derailed/k9s/pull/2516) Added defaultsToFullScreen flag for Live/Details view,logs

---

<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)
15 changes: 8 additions & 7 deletions internal/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func (a *APIClient) ConnectionOK() bool {
return a.connOK
}

func makeSAR(ns, gvr string) *authorizationv1.SelfSubjectAccessReview {
func makeSAR(ns, gvr, name string) *authorizationv1.SelfSubjectAccessReview {
if ns == ClusterScope {
ns = BlankNamespace
}
Expand All @@ -98,13 +98,14 @@ func makeSAR(ns, gvr string) *authorizationv1.SelfSubjectAccessReview {
Version: res.Version,
Resource: res.Resource,
Subresource: spec.SubResource(),
Name: name,
},
},
}
}

func makeCacheKey(ns, gvr string, vv []string) string {
return ns + ":" + gvr + "::" + strings.Join(vv, ",")
func makeCacheKey(ns, gvr, n string, vv []string) string {
return ns + ":" + gvr + ":" + n + "::" + strings.Join(vv, ",")
}

// ActiveContext returns the current context name.
Expand Down Expand Up @@ -142,14 +143,14 @@ func (a *APIClient) clearCache() {
}

// CanI checks if user has access to a certain resource.
func (a *APIClient) CanI(ns, gvr string, verbs []string) (auth bool, err error) {
func (a *APIClient) CanI(ns, gvr, name string, verbs []string) (auth bool, err error) {
if !a.getConnOK() {
return false, errors.New("ACCESS -- No API server connection")
}
if IsClusterWide(ns) {
ns = BlankNamespace
}
key := makeCacheKey(ns, gvr, verbs)
key := makeCacheKey(ns, gvr, name, verbs)
if v, ok := a.cache.Get(key); ok {
if auth, ok = v.(bool); ok {
return auth, nil
Expand All @@ -160,7 +161,7 @@ func (a *APIClient) CanI(ns, gvr string, verbs []string) (auth bool, err error)
if err != nil {
return false, err
}
client, sar := dial.AuthorizationV1().SelfSubjectAccessReviews(), makeSAR(ns, gvr)
client, sar := dial.AuthorizationV1().SelfSubjectAccessReviews(), makeSAR(ns, gvr, name)

ctx, cancel := context.WithTimeout(context.Background(), a.config.CallTimeout())
defer cancel()
Expand Down Expand Up @@ -215,7 +216,7 @@ func (a *APIClient) IsValidNamespace(ns string) bool {
return true
}

ok, err := a.CanI(ClusterScope, "v1/namespaces", []string{ListVerb})
ok, err := a.CanI(ClusterScope, "v1/namespaces", "", []string{ListVerb})
if ok && err == nil {
nn, _ := a.ValidNamespaceNames()
_, ok = nn[ns]
Expand Down
2 changes: 1 addition & 1 deletion internal/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func TestMakeSAR(t *testing.T) {
for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
assert.Equal(t, u.sar, makeSAR(u.ns, u.gvr.String()))
assert.Equal(t, u.sar, makeSAR(u.ns, u.gvr.String(), ""))
})
}
}
Expand Down
2 changes: 1 addition & 1 deletion internal/client/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func (m *MetricsServer) checkAccess(ns, gvr, msg string) error {
return errors.New("no metrics-server detected on cluster")
}

auth, err := m.CanI(ns, gvr, ListAccess)
auth, err := m.CanI(ns, gvr, "", ListAccess)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/client/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ type PodsMetricsMap map[string]*mv1beta1.PodMetrics
// Authorizer checks what a user can or cannot do to a resource.
type Authorizer interface {
// CanI returns true if the user can use these actions for a given resource.
CanI(ns, gvr string, verbs []string) (bool, error)
CanI(ns, gvr, n string, verbs []string) (bool, error)
}

// Connection represents a Kubernetes apiserver connection.
Expand Down
14 changes: 14 additions & 0 deletions internal/config/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ func NewAliases() *Aliases {
}
}

func (a *Aliases) AliasesFor(s string) []string {
aa := make([]string, 0, 10)

a.mx.RLock()
defer a.mx.RUnlock()
for k, v := range a.Alias {
if v == s {
aa = append(aa, k)
}
}

return aa
}

// Keys returns all aliases keys.
func (a *Aliases) Keys() []string {
a.mx.RLock()
Expand Down
2 changes: 1 addition & 1 deletion internal/config/mock/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func NewMockConnectionWithContext(ct string) mockConnection {
return mockConnection{ct: ct}
}

func (m mockConnection) CanI(ns, gvr string, verbs []string) (bool, error) {
func (m mockConnection) CanI(ns, gvr, n string, verbs []string) (bool, error) {
return true, nil
}
func (m mockConnection) Config() *client.Config {
Expand Down
4 changes: 4 additions & 0 deletions internal/dao/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ func NewAlias(f Factory) *Alias {
return &a
}

func (a *Alias) AliasesFor(s string) []string {
return a.Aliases.AliasesFor(s)
}

// Check verifies an alias is defined for this command.
func (a *Alias) Check(cmd string) (string, bool) {
return a.Aliases.Get(cmd)
Expand Down
16 changes: 8 additions & 8 deletions internal/dao/container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,14 @@ func (c *conn) ValidNamespaces() ([]v1.Namespace, error) { return n
func (c *conn) SupportsRes(grp string, versions []string) (string, bool, error) {
return "", false, nil
}
func (c *conn) ServerVersion() (*version.Info, error) { return nil, nil }
func (c *conn) CurrentNamespaceName() (string, error) { return "", nil }
func (c *conn) CanI(ns, gvr string, verbs []string) (bool, error) { return true, nil }
func (c *conn) ActiveContext() string { return "" }
func (c *conn) ActiveNamespace() string { return "" }
func (c *conn) IsValidNamespace(string) bool { return true }
func (c *conn) ValidNamespaceNames() (client.NamespaceNames, error) { return nil, nil }
func (c *conn) IsActiveNamespace(string) bool { return false }
func (c *conn) ServerVersion() (*version.Info, error) { return nil, nil }
func (c *conn) CurrentNamespaceName() (string, error) { return "", nil }
func (c *conn) CanI(ns, gvr, n string, verbs []string) (bool, error) { return true, nil }
func (c *conn) ActiveContext() string { return "" }
func (c *conn) ActiveNamespace() string { return "" }
func (c *conn) IsValidNamespace(string) bool { return true }
func (c *conn) ValidNamespaceNames() (client.NamespaceNames, error) { return nil, nil }
func (c *conn) IsActiveNamespace(string) bool { return false }

type podFactory struct{}

Expand Down
6 changes: 3 additions & 3 deletions internal/dao/cronjob.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ func (c *CronJob) ListImages(ctx context.Context, fqn string) ([]string, error)

// Run a CronJob.
func (c *CronJob) Run(path string) error {
ns, _ := client.Namespaced(path)
auth, err := c.Client().CanI(ns, jobGVR, []string{client.GetVerb, client.CreateVerb})
ns, n := client.Namespaced(path)
auth, err := c.Client().CanI(ns, jobGVR, n, []string{client.GetVerb, client.CreateVerb})
if err != nil {
return err
}
Expand Down Expand Up @@ -144,7 +144,7 @@ func (c *CronJob) GetInstance(fqn string) (*batchv1.CronJob, error) {
// ToggleSuspend toggles suspend/resume on a CronJob.
func (c *CronJob) ToggleSuspend(ctx context.Context, path string) error {
ns, n := client.Namespaced(path)
auth, err := c.Client().CanI(ns, c.GVR(), []string{client.GetVerb, client.UpdateVerb})
auth, err := c.Client().CanI(ns, c.GVR(), n, []string{client.GetVerb, client.UpdateVerb})
if err != nil {
return err
}
Expand Down
6 changes: 3 additions & 3 deletions internal/dao/dp.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (d *Deployment) IsHappy(dp appsv1.Deployment) bool {
// Scale a Deployment.
func (d *Deployment) Scale(ctx context.Context, path string, replicas int32) error {
ns, n := client.Namespaced(path)
auth, err := d.Client().CanI(ns, "apps/v1/deployments:scale", []string{client.GetVerb, client.UpdateVerb})
auth, err := d.Client().CanI(ns, "apps/v1/deployments:scale", n, []string{client.GetVerb, client.UpdateVerb})
if err != nil {
return err
}
Expand Down Expand Up @@ -91,7 +91,7 @@ func (d *Deployment) Restart(ctx context.Context, path string) error {
return err
}

auth, err := d.Client().CanI(dp.Namespace, "apps/v1/deployments", []string{client.PatchVerb})
auth, err := d.Client().CanI(dp.Namespace, "apps/v1/deployments", dp.Name, []string{client.PatchVerb})
if err != nil {
return err
}
Expand Down Expand Up @@ -266,7 +266,7 @@ func (d *Deployment) GetPodSpec(path string) (*v1.PodSpec, error) {
// SetImages sets container images.
func (d *Deployment) SetImages(ctx context.Context, path string, imageSpecs ImageSpecs) error {
ns, n := client.Namespaced(path)
auth, err := d.Client().CanI(ns, "apps/v1/deployments", []string{client.PatchVerb})
auth, err := d.Client().CanI(ns, "apps/v1/deployments", n, []string{client.PatchVerb})
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions internal/dao/ds.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func (d *DaemonSet) Restart(ctx context.Context, path string) error {
return err
}

auth, err := d.Client().CanI(ds.Namespace, "apps/v1/daemonsets", []string{client.PatchVerb})
auth, err := d.Client().CanI(ds.Namespace, "apps/v1/daemonsets", ds.Name, []string{client.PatchVerb})
if err != nil {
return err
}
Expand Down Expand Up @@ -285,7 +285,7 @@ func (d *DaemonSet) GetPodSpec(path string) (*v1.PodSpec, error) {
// SetImages sets container images.
func (d *DaemonSet) SetImages(ctx context.Context, path string, imageSpecs ImageSpecs) error {
ns, n := client.Namespaced(path)
auth, err := d.Client().CanI(ns, "apps/v1/daemonset", []string{client.PatchVerb})
auth, err := d.Client().CanI(ns, "apps/v1/daemonset", n, []string{client.PatchVerb})
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/dao/generic.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func (g *Generic) ToYAML(path string, showManaged bool) (string, error) {
// Delete deletes a resource.
func (g *Generic) Delete(ctx context.Context, path string, propagation *metav1.DeletionPropagation, grace Grace) error {
ns, n := client.Namespaced(path)
auth, err := g.Client().CanI(ns, g.gvrStr(), []string{client.DeleteVerb})
auth, err := g.Client().CanI(ns, g.gvrStr(), n, []string{client.DeleteVerb})
if err != nil {
return err
}
Expand Down
7 changes: 4 additions & 3 deletions internal/dao/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func (n *Node) Drain(path string, opts DrainOptions, w io.Writer) error {
dd, errs := h.GetPodsForDeletion(path)
if len(errs) != 0 {
for _, e := range errs {
if _, err := h.ErrOut.Write([]byte(e.Error() + "\n")); err != nil {
if _, err := h.ErrOut.Write([]byte(fmt.Sprintf("[%s] %s\n", path, e.Error()))); err != nil {
return err
}
}
Expand Down Expand Up @@ -247,7 +247,8 @@ func (n *Node) ensureCordoned(path string) (bool, error) {

// FetchNode retrieves a node.
func FetchNode(ctx context.Context, f Factory, path string) (*v1.Node, error) {
auth, err := f.Client().CanI(client.ClusterScope, "v1/nodes", []string{"get"})
_, n := client.Namespaced(path)
auth, err := f.Client().CanI(client.ClusterScope, "v1/nodes", n, []string{"get"})
if err != nil {
return nil, err
}
Expand All @@ -271,7 +272,7 @@ func FetchNode(ctx context.Context, f Factory, path string) (*v1.Node, error) {

// FetchNodes retrieves all nodes.
func FetchNodes(ctx context.Context, f Factory, labelsSel string) (*v1.NodeList, error) {
auth, err := f.Client().CanI(client.ClusterScope, "v1/nodes", []string{client.ListVerb})
auth, err := f.Client().CanI(client.ClusterScope, "v1/nodes", "", []string{client.ListVerb})
if err != nil {
return nil, err
}
Expand Down
7 changes: 3 additions & 4 deletions internal/dao/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,16 +132,15 @@ func (p *Pod) List(ctx context.Context, ns string) ([]runtime.Object, error) {

// Logs fetch container logs for a given pod and container.
func (p *Pod) Logs(path string, opts *v1.PodLogOptions) (*restclient.Request, error) {
ns, _ := client.Namespaced(path)
auth, err := p.Client().CanI(ns, "v1/pods:log", []string{client.GetVerb})
ns, n := client.Namespaced(path)
auth, err := p.Client().CanI(ns, "v1/pods:log", n, []string{client.GetVerb})
if err != nil {
return nil, err
}
if !auth {
return nil, fmt.Errorf("user is not authorized to view pod logs")
}

ns, n := client.Namespaced(path)
dial, err := p.Client().DialLogs()
if err != nil {
return nil, err
Expand Down Expand Up @@ -457,7 +456,7 @@ func (p *Pod) GetPodSpec(path string) (*v1.PodSpec, error) {
// SetImages sets container images.
func (p *Pod) SetImages(ctx context.Context, path string, imageSpecs ImageSpecs) error {
ns, n := client.Namespaced(path)
auth, err := p.Client().CanI(ns, "v1/pod", []string{client.PatchVerb})
auth, err := p.Client().CanI(ns, "v1/pod", n, []string{client.PatchVerb})
if err != nil {
return err
}
Expand Down
Loading

0 comments on commit f2f4077

Please sign in to comment.