diff --git a/Makefile b/Makefile index 65b99d45..83b50679 100644 --- a/Makefile +++ b/Makefile @@ -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.25.4 +VERSION ?= v0.25.5 IMG_NAME := derailed/k9s IMAGE := ${IMG_NAME}:${VERSION} diff --git a/change_logs/release_v0.25.5.md b/change_logs/release_v0.25.5.md new file mode 100644 index 00000000..59457542 --- /dev/null +++ b/change_logs/release_v0.25.5.md @@ -0,0 +1,26 @@ + + +# Release v0.25.5 + +## 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! + +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! + +--- + +## Resolved Issues + +* [Issue #1327](https://github.com/derailed/k9s/issues/1327) Switching K8s resource changes view to all namespace +* [Issue #1326](https://github.com/derailed/k9s/issues/1326) Port forwarding not possible because of "invalid container port" +* [Issue #1325](https://github.com/derailed/k9s/issues/1325) Meaning of number in brackets after context name is unclear +* [Issue #1324](https://github.com/derailed/k9s/issues/1324) Problem with Configuration for macOS is can't find configuration directory + +--- + + © 2020 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0) diff --git a/internal/client/config.go b/internal/client/config.go index 2ef1c074..e3088871 100644 --- a/internal/client/config.go +++ b/internal/client/config.go @@ -92,7 +92,7 @@ func (c *Config) SwitchContext(name string) error { } context, err := c.GetContext(name) if err != nil { - return fmt.Errorf("context %s does not exist", name) + return fmt.Errorf("context %q does not exist", name) } c.flags.Context = &name c.flags.ClusterName = &(context.Cluster) diff --git a/internal/dao/log_item.go b/internal/dao/log_item.go index 0193f2f3..877325ea 100644 --- a/internal/dao/log_item.go +++ b/internal/dao/log_item.go @@ -84,7 +84,7 @@ func (l *LogItem) Render(paint string, showTime bool, bb *bytes.Buffer) { } bb.WriteString("[" + paint + "::b]" + l.Container + "[-::-] ") } else if len(l.Pod) > 0 { - bb.WriteString("[-::]") + bb.WriteString("[-::] ") } if index > 0 { diff --git a/internal/dao/log_item_test.go b/internal/dao/log_item_test.go index 63116cd6..9f6a59bf 100644 --- a/internal/dao/log_item_test.go +++ b/internal/dao/log_item_test.go @@ -31,17 +31,20 @@ func TestLogItemEmpty(t *testing.T) { func TestLogItemRender(t *testing.T) { uu := map[string]struct { opts dao.LogOptions + log string e string }{ "empty": { opts: dao.LogOptions{}, + log: fmt.Sprintf("%s %s\n", "2018-12-14T10:36:43.326972-07:00", "Testing 1,2,3..."), e: "Testing 1,2,3...\n", }, "container": { opts: dao.LogOptions{ Container: "fred", }, - e: "[yellow::b]fred[-::-] Testing 1,2,3...\n", + log: fmt.Sprintf("%s %s\n", "2018-12-14T10:36:43.326972-07:00", "Testing 1,2,3..."), + e: "[yellow::b]fred[-::-] Testing 1,2,3...\n", }, "pod": { opts: dao.LogOptions{ @@ -49,7 +52,8 @@ func TestLogItemRender(t *testing.T) { Container: "blee", SingleContainer: true, }, - e: "[yellow::]fred [yellow::b]blee[-::-] Testing 1,2,3...\n", + log: fmt.Sprintf("%s %s\n", "2018-12-14T10:36:43.326972-07:00", "Testing 1,2,3..."), + e: "[yellow::]fred [yellow::b]blee[-::-] Testing 1,2,3...\n", }, "full": { opts: dao.LogOptions{ @@ -58,15 +62,25 @@ func TestLogItemRender(t *testing.T) { SingleContainer: true, ShowTimestamp: true, }, - e: "[gray::]2018-12-14T10:36:43.326972-07:00 [yellow::]fred [yellow::b]blee[-::-] Testing 1,2,3...\n", + log: fmt.Sprintf("%s %s\n", "2018-12-14T10:36:43.326972-07:00", "Testing 1,2,3..."), + e: "[gray::]2018-12-14T10:36:43.326972-07:00 [yellow::]fred [yellow::b]blee[-::-] Testing 1,2,3...\n", + }, + "log-level": { + opts: dao.LogOptions{ + Path: "blee/fred", + Container: "", + SingleContainer: false, + ShowTimestamp: false, + }, + log: fmt.Sprintf("%s %s\n", "2018-12-14T10:36:43.326972-07:00", "2021-10-28T13:06:37Z [INFO] [blah-blah] Testing 1,2,3..."), + e: "[yellow::]fred[-::] 2021-10-28T13:06:37Z [INFO] [blah-blah] Testing 1,2,3...\n", }, } - s := []byte(fmt.Sprintf("%s %s\n", "2018-12-14T10:36:43.326972-07:00", "Testing 1,2,3...")) for k := range uu { u := uu[k] t.Run(k, func(t *testing.T) { - i := dao.NewLogItem(s) + i := dao.NewLogItem([]byte(u.log)) _, n := client.Namespaced(u.opts.Path) i.Pod, i.Container = n, u.opts.Container diff --git a/internal/port/co_portspec.go b/internal/port/co_portspec.go index 41b8ce52..ab24acc4 100644 --- a/internal/port/co_portspec.go +++ b/internal/port/co_portspec.go @@ -22,6 +22,10 @@ func (c ContainerPortSpecs) Dump() string { // InSpecs checks if given port matches a spec. func (c ContainerPortSpecs) MatchSpec(s string) bool { + // No port are exposed + if len(c) == 0 { + return true + } for _, spec := range c { if spec.MatchSpec(s) { return true diff --git a/internal/view/browser.go b/internal/view/browser.go index 1874beb2..5c880abc 100644 --- a/internal/view/browser.go +++ b/internal/view/browser.go @@ -127,7 +127,7 @@ func (b *Browser) SetInstance(path string) { // Start initializes browser updates. func (b *Browser) Start() { b.app.Config.ValidateFavorites() - if err := b.app.switchNS(b.GetModel().GetNamespace()); err != nil { + if err := b.app.switchNS(b.app.Config.ActiveNamespace()); err != nil { log.Error().Err(err).Msgf("ns switch failed") } if err := b.app.Config.Save(); err != nil { diff --git a/internal/view/cluster_info.go b/internal/view/cluster_info.go index ae047759..6baaefa7 100644 --- a/internal/view/cluster_info.go +++ b/internal/view/cluster_info.go @@ -2,7 +2,6 @@ package view import ( "fmt" - "runtime" "github.com/derailed/k9s/internal/client" "github.com/derailed/k9s/internal/config" @@ -103,7 +102,7 @@ func (c *ClusterInfo) ClusterInfoChanged(prev, curr model.ClusterMeta) { c.app.QueueUpdateDraw(func() { c.Clear() c.layout() - row := c.setCell(0, fmt.Sprintf("%s [%d]", curr.Context, runtime.NumGoroutine())) + row := c.setCell(0, curr.Context) row = c.setCell(row, curr.Cluster) row = c.setCell(row, curr.User) if curr.K9sLatest != "" { diff --git a/internal/view/command.go b/internal/view/command.go index 448d3a43..1c70ef5b 100644 --- a/internal/view/command.go +++ b/internal/view/command.go @@ -156,12 +156,15 @@ func (c *Command) defaultCmd() error { tokens := strings.Split(view, " ") cmd := view if len(tokens) == 1 { - cmd = tokens[0] + " " + c.app.Config.ActiveNamespace() + if !isContextCmd(tokens[0]) { + cmd = tokens[0] + " " + c.app.Config.ActiveNamespace() + } } if err := c.run(cmd, "", true); err != nil { - log.Error().Err(err).Msgf("Default run command failed") - return c.run("meow", err.Error(), true) + log.Error().Err(err).Msgf("Default run command failed %q", cmd) + c.app.cowCmd(err.Error()) + return err } return nil } diff --git a/internal/view/pf_dialog.go b/internal/view/pf_dialog.go index b3119e62..360fb161 100644 --- a/internal/view/pf_dialog.go +++ b/internal/view/pf_dialog.go @@ -41,7 +41,7 @@ func ShowPortForwards(v ResourceViewer, path string, ports port.ContainerPortSpe f.AddInputField("Container Port:", p1, fieldLen, nil, nil) coField := f.GetFormItemByLabel("Container Port:").(*tview.InputField) if coField.GetText() == "" { - coField.SetPlaceholder("Enter a container name/port") + coField.SetPlaceholder("Enter a container name::port") } f.AddInputField("Local Port:", p2, fieldLen, nil, nil) loField := f.GetFormItemByLabel("Local Port:").(*tview.InputField)