release v0.25.11 (#1377)
parent
e64dcbcbdc
commit
11c2ae2622
2
Makefile
2
Makefile
|
|
@ -5,7 +5,7 @@ PACKAGE := github.com/derailed/$(NAME)
|
||||||
GIT_REV ?= $(shell git rev-parse --short HEAD)
|
GIT_REV ?= $(shell git rev-parse --short HEAD)
|
||||||
SOURCE_DATE_EPOCH ?= $(shell date +%s)
|
SOURCE_DATE_EPOCH ?= $(shell date +%s)
|
||||||
DATE ?= $(shell date -u -d @${SOURCE_DATE_EPOCH} +"%Y-%m-%dT%H:%M:%SZ")
|
DATE ?= $(shell date -u -d @${SOURCE_DATE_EPOCH} +"%Y-%m-%dT%H:%M:%SZ")
|
||||||
VERSION ?= v0.25.10
|
VERSION ?= v0.25.11
|
||||||
IMG_NAME := derailed/k9s
|
IMG_NAME := derailed/k9s
|
||||||
IMAGE := ${IMG_NAME}:${VERSION}
|
IMAGE := ${IMG_NAME}:${VERSION}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/k9s_small.png" align="right" width="200" height="auto"/>
|
||||||
|
|
||||||
|
# Release v0.25.11
|
||||||
|
|
||||||
|
## 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)
|
||||||
|
|
||||||
|
### A Word From Our Sponsors...
|
||||||
|
|
||||||
|
I want to recognize the following folks that have been kind enough to join our sponsorship program and opted to `pay it forward`!
|
||||||
|
|
||||||
|
* [Joshua Kapellen](https://github.com/joshuakapellen)
|
||||||
|
* [Qdentity](https://github.com/qdentity)
|
||||||
|
* [Maxim](https://github.com/bsod90)
|
||||||
|
* [Sönke Schau](https://github.com/xgcssch)
|
||||||
|
|
||||||
|
So if you feel K9s is helping with your productivity while administering your Kubernetes clusters, please consider pitching in as it will go a long way in ensuring a thriving environment for this repo and our k9ers community at large.
|
||||||
|
|
||||||
|
Also please take some time and give a huge shoot out to all the good folks below that have spent time plowing thru the code to help improve K9s for all of us!
|
||||||
|
|
||||||
|
Thank you!!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Maintenance Release!
|
||||||
|
|
||||||
|
Hoy! end of year suck... Feeling the burn ;( Apologize for the disruptions...
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Resolved Issues
|
||||||
|
|
||||||
|
* [Issue #1374](https://github.com/derailed/k9s/issues/1374) --all-namespaces does not work v0.25.10
|
||||||
|
* [Issue #1376](https://github.com/derailed/k9s/issues/1376) Events not sorted correctly by dates
|
||||||
|
* [Issue #1373](https://github.com/derailed/k9s/issues/1373) change namespace not possible
|
||||||
|
|
||||||
|
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/imhotep_logo.png" width="32" height="auto"/> © 2021 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
|
@ -23,9 +23,8 @@ const (
|
||||||
|
|
||||||
// Config tracks a kubernetes configuration.
|
// Config tracks a kubernetes configuration.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
flags *genericclioptions.ConfigFlags
|
flags *genericclioptions.ConfigFlags
|
||||||
mutex *sync.RWMutex
|
mutex *sync.RWMutex
|
||||||
OverrideNS bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConfig returns a new k8s config or an error if the flags are invalid.
|
// NewConfig returns a new k8s config or an error if the flags are invalid.
|
||||||
|
|
@ -183,15 +182,15 @@ func (c *Config) CurrentClusterName() (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClusterNames fetch all kubeconfig defined clusters.
|
// ClusterNames fetch all kubeconfig defined clusters.
|
||||||
func (c *Config) ClusterNames() ([]string, error) {
|
func (c *Config) ClusterNames() (map[string]struct{}, error) {
|
||||||
cfg, err := c.RawConfig()
|
cfg, err := c.RawConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cc := make([]string, 0, len(cfg.Clusters))
|
cc := make(map[string]struct{}, len(cfg.Clusters))
|
||||||
for name := range cfg.Clusters {
|
for name := range cfg.Clusters {
|
||||||
cc = append(cc, name)
|
cc[name] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cc, nil
|
return cc, nil
|
||||||
|
|
|
||||||
|
|
@ -36,15 +36,14 @@ type (
|
||||||
CurrentNamespaceName() (string, error)
|
CurrentNamespaceName() (string, error)
|
||||||
|
|
||||||
// ClusterNames() returns all available cluster names.
|
// ClusterNames() returns all available cluster names.
|
||||||
ClusterNames() ([]string, error)
|
ClusterNames() (map[string]struct{}, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config tracks K9s configuration options.
|
// Config tracks K9s configuration options.
|
||||||
Config struct {
|
Config struct {
|
||||||
K9s *K9s `yaml:"k9s"`
|
K9s *K9s `yaml:"k9s"`
|
||||||
client client.Connection
|
client client.Connection
|
||||||
settings KubeSettings
|
settings KubeSettings
|
||||||
overrideNS bool
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -94,11 +93,10 @@ func (c *Config) Refine(flags *genericclioptions.ConfigFlags, k9sFlags *Flags, c
|
||||||
c.K9s.ActivateCluster()
|
c.K9s.ActivateCluster()
|
||||||
|
|
||||||
var ns string
|
var ns string
|
||||||
var override bool
|
|
||||||
if k9sFlags != nil && IsBoolSet(k9sFlags.AllNamespaces) {
|
if k9sFlags != nil && IsBoolSet(k9sFlags.AllNamespaces) {
|
||||||
ns, override = client.NamespaceAll, true
|
ns = client.NamespaceAll
|
||||||
} else if isSet(flags.Namespace) {
|
} else if isSet(flags.Namespace) {
|
||||||
ns, override = *flags.Namespace, true
|
ns = *flags.Namespace
|
||||||
} else if context.Namespace != "" {
|
} else if context.Namespace != "" {
|
||||||
ns = context.Namespace
|
ns = context.Namespace
|
||||||
} else if cl := c.K9s.ActiveCluster(); cl != nil {
|
} else if cl := c.K9s.ActiveCluster(); cl != nil {
|
||||||
|
|
@ -109,7 +107,7 @@ func (c *Config) Refine(flags *genericclioptions.ConfigFlags, k9sFlags *Flags, c
|
||||||
if err := c.SetActiveNamespace(ns); err != nil {
|
if err := c.SetActiveNamespace(ns); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
flags.Namespace, c.overrideNS = &ns, override
|
flags.Namespace = &ns
|
||||||
}
|
}
|
||||||
|
|
||||||
if isSet(flags.ClusterName) {
|
if isSet(flags.ClusterName) {
|
||||||
|
|
@ -142,6 +140,9 @@ func (c *Config) ActiveNamespace() string {
|
||||||
return "default"
|
return "default"
|
||||||
}
|
}
|
||||||
cl := c.CurrentCluster()
|
cl := c.CurrentCluster()
|
||||||
|
if cl != nil && cl.Namespace != nil {
|
||||||
|
return cl.Namespace.Active
|
||||||
|
}
|
||||||
if cl == nil {
|
if cl == nil {
|
||||||
cl = NewCluster()
|
cl = NewCluster()
|
||||||
c.K9s.Clusters[c.K9s.CurrentCluster] = cl
|
c.K9s.Clusters[c.K9s.CurrentCluster] = cl
|
||||||
|
|
@ -154,10 +155,6 @@ func (c *Config) ActiveNamespace() string {
|
||||||
return ns
|
return ns
|
||||||
}
|
}
|
||||||
|
|
||||||
if cl.Namespace != nil {
|
|
||||||
return cl.Namespace.Active
|
|
||||||
}
|
|
||||||
|
|
||||||
return "default"
|
return "default"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -221,9 +218,6 @@ func (c *Config) GetConnection() client.Connection {
|
||||||
// SetConnection set an api server connection.
|
// SetConnection set an api server connection.
|
||||||
func (c *Config) SetConnection(conn client.Connection) {
|
func (c *Config) SetConnection(conn client.Connection) {
|
||||||
c.client = conn
|
c.client = conn
|
||||||
if c.client != nil && c.client.Config() != nil {
|
|
||||||
c.client.Config().OverrideNS = c.overrideNS
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load K9s configuration from file.
|
// Load K9s configuration from file.
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,7 @@ func TestConfigSaveFile(t *testing.T) {
|
||||||
m.When(mk.CurrentContextName()).ThenReturn("minikube", nil)
|
m.When(mk.CurrentContextName()).ThenReturn("minikube", nil)
|
||||||
m.When(mk.CurrentClusterName()).ThenReturn("minikube", nil)
|
m.When(mk.CurrentClusterName()).ThenReturn("minikube", nil)
|
||||||
m.When(mk.CurrentNamespaceName()).ThenReturn("default", nil)
|
m.When(mk.CurrentNamespaceName()).ThenReturn("default", nil)
|
||||||
m.When(mk.ClusterNames()).ThenReturn([]string{"minikube", "fred", "blee"}, nil)
|
m.When(mk.ClusterNames()).ThenReturn(map[string]struct{}{"minikube": {}, "fred": {}, "blee": {}}, nil)
|
||||||
m.When(mk.NamespaceNames(namespaces())).ThenReturn([]string{"default"})
|
m.When(mk.NamespaceNames(namespaces())).ThenReturn([]string{"default"})
|
||||||
|
|
||||||
cfg := config.NewConfig(mk)
|
cfg := config.NewConfig(mk)
|
||||||
|
|
@ -228,7 +228,7 @@ func TestConfigReset(t *testing.T) {
|
||||||
m.When(mk.CurrentContextName()).ThenReturn("blee", nil)
|
m.When(mk.CurrentContextName()).ThenReturn("blee", nil)
|
||||||
m.When(mk.CurrentClusterName()).ThenReturn("blee", nil)
|
m.When(mk.CurrentClusterName()).ThenReturn("blee", nil)
|
||||||
m.When(mk.CurrentNamespaceName()).ThenReturn("default", nil)
|
m.When(mk.CurrentNamespaceName()).ThenReturn("default", nil)
|
||||||
m.When(mk.ClusterNames()).ThenReturn([]string{"blee"}, nil)
|
m.When(mk.ClusterNames()).ThenReturn(map[string]struct{}{"blee": {}}, nil)
|
||||||
m.When(mk.NamespaceNames(namespaces())).ThenReturn([]string{"default"})
|
m.When(mk.NamespaceNames(namespaces())).ThenReturn([]string{"default"})
|
||||||
|
|
||||||
cfg := config.NewConfig(mk)
|
cfg := config.NewConfig(mk)
|
||||||
|
|
@ -271,7 +271,7 @@ func (m *mockSettings) CurrentClusterName() (string, error) { return "", nil }
|
||||||
func (m *mockSettings) CurrentNamespaceName() (string, error) {
|
func (m *mockSettings) CurrentNamespaceName() (string, error) {
|
||||||
return *m.flags.Namespace, nil
|
return *m.flags.Namespace, nil
|
||||||
}
|
}
|
||||||
func (m *mockSettings) ClusterNames() ([]string, error) { return nil, nil }
|
func (m *mockSettings) ClusterNames() (map[string]struct{}, error) { return nil, nil }
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Test Data...
|
// Test Data...
|
||||||
|
|
|
||||||
|
|
@ -194,9 +194,9 @@ func (k *K9s) validateClusters(c client.Connection, ks KubeSettings) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for key := range k.Clusters {
|
for key, cluster := range k.Clusters {
|
||||||
k.Clusters[key].Validate(c, ks)
|
cluster.Validate(c, ks)
|
||||||
if InList(cc, key) {
|
if _, ok := cc[key]; ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if k.CurrentCluster == key {
|
if k.CurrentCluster == key {
|
||||||
|
|
@ -224,8 +224,8 @@ func (k *K9s) Validate(c client.Connection, ks KubeSettings) {
|
||||||
}
|
}
|
||||||
k.Thresholds.Validate(c, ks)
|
k.Thresholds.Validate(c, ks)
|
||||||
|
|
||||||
if ctx, err := ks.CurrentContextName(); err == nil && len(k.CurrentContext) == 0 {
|
if context, err := ks.CurrentContextName(); err == nil && len(k.CurrentContext) == 0 {
|
||||||
k.CurrentContext = ctx
|
k.CurrentContext = context
|
||||||
k.CurrentCluster = ""
|
k.CurrentCluster = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ func TestK9sValidate(t *testing.T) {
|
||||||
mk := NewMockKubeSettings()
|
mk := NewMockKubeSettings()
|
||||||
m.When(mk.CurrentContextName()).ThenReturn("ctx1", nil)
|
m.When(mk.CurrentContextName()).ThenReturn("ctx1", nil)
|
||||||
m.When(mk.CurrentClusterName()).ThenReturn("c1", nil)
|
m.When(mk.CurrentClusterName()).ThenReturn("c1", nil)
|
||||||
m.When(mk.ClusterNames()).ThenReturn([]string{"c1", "c2"}, nil)
|
m.When(mk.ClusterNames()).ThenReturn(map[string]struct{}{"c1": {}, "c2": {}}, nil)
|
||||||
m.When(mk.NamespaceNames(namespaces())).ThenReturn([]string{"default"})
|
m.When(mk.NamespaceNames(namespaces())).ThenReturn([]string{"default"})
|
||||||
|
|
||||||
c := config.NewK9s()
|
c := config.NewK9s()
|
||||||
|
|
@ -90,7 +90,7 @@ func TestK9sValidateBlank(t *testing.T) {
|
||||||
mk := NewMockKubeSettings()
|
mk := NewMockKubeSettings()
|
||||||
m.When(mk.CurrentContextName()).ThenReturn("ctx1", nil)
|
m.When(mk.CurrentContextName()).ThenReturn("ctx1", nil)
|
||||||
m.When(mk.CurrentClusterName()).ThenReturn("c1", nil)
|
m.When(mk.CurrentClusterName()).ThenReturn("c1", nil)
|
||||||
m.When(mk.ClusterNames()).ThenReturn([]string{"c1", "c2"}, nil)
|
m.When(mk.ClusterNames()).ThenReturn(map[string]struct{}{"c1": {}, "c2": {}}, nil)
|
||||||
m.When(mk.NamespaceNames(namespaces())).ThenReturn([]string{"default"})
|
m.When(mk.NamespaceNames(namespaces())).ThenReturn([]string{"default"})
|
||||||
|
|
||||||
var c config.K9s
|
var c config.K9s
|
||||||
|
|
|
||||||
|
|
@ -25,17 +25,17 @@ func NewMockKubeSettings(options ...pegomock.Option) *MockKubeSettings {
|
||||||
func (mock *MockKubeSettings) SetFailHandler(fh pegomock.FailHandler) { mock.fail = fh }
|
func (mock *MockKubeSettings) SetFailHandler(fh pegomock.FailHandler) { mock.fail = fh }
|
||||||
func (mock *MockKubeSettings) FailHandler() pegomock.FailHandler { return mock.fail }
|
func (mock *MockKubeSettings) FailHandler() pegomock.FailHandler { return mock.fail }
|
||||||
|
|
||||||
func (mock *MockKubeSettings) ClusterNames() ([]string, error) {
|
func (mock *MockKubeSettings) ClusterNames() (map[string]struct{}, error) {
|
||||||
if mock == nil {
|
if mock == nil {
|
||||||
panic("mock must not be nil. Use myMock := NewMockKubeSettings().")
|
panic("mock must not be nil. Use myMock := NewMockKubeSettings().")
|
||||||
}
|
}
|
||||||
params := []pegomock.Param{}
|
params := []pegomock.Param{}
|
||||||
result := pegomock.GetGenericMockFrom(mock).Invoke("ClusterNames", params, []reflect.Type{reflect.TypeOf((*[]string)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
|
result := pegomock.GetGenericMockFrom(mock).Invoke("ClusterNames", params, []reflect.Type{reflect.TypeOf((*map[string]struct{})(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
|
||||||
var ret0 []string
|
var ret0 map[string]struct{}
|
||||||
var ret1 error
|
var ret1 error
|
||||||
if len(result) != 0 {
|
if len(result) != 0 {
|
||||||
if result[0] != nil {
|
if result[0] != nil {
|
||||||
ret0 = result[0].([]string)
|
ret0 = result[0].(map[string]struct{})
|
||||||
}
|
}
|
||||||
if result[1] != nil {
|
if result[1] != nil {
|
||||||
ret1 = result[1].(error)
|
ret1 = result[1].(error)
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,10 @@ var Registry = map[string]ResourceMeta{
|
||||||
"v1/persistentvolumeclaims": {
|
"v1/persistentvolumeclaims": {
|
||||||
Renderer: &render.PersistentVolumeClaim{},
|
Renderer: &render.PersistentVolumeClaim{},
|
||||||
},
|
},
|
||||||
|
"v1/events": {
|
||||||
|
DAO: &dao.Table{},
|
||||||
|
Renderer: &render.Event{},
|
||||||
|
},
|
||||||
|
|
||||||
// Apps...
|
// Apps...
|
||||||
"apps/v1/deployments": {
|
"apps/v1/deployments": {
|
||||||
|
|
|
||||||
|
|
@ -240,7 +240,7 @@ func (t *Table) reconcile(ctx context.Context) error {
|
||||||
|
|
||||||
var rows render.Rows
|
var rows render.Rows
|
||||||
if len(oo) > 0 {
|
if len(oo) > 0 {
|
||||||
if _, ok := meta.Renderer.(*render.Generic); ok {
|
if meta.Renderer.IsGeneric() {
|
||||||
table, ok := oo[0].(*metav1beta1.Table)
|
table, ok := oo[0].(*metav1beta1.Table)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("expecting a meta table but got %T", oo[0])
|
return fmt.Errorf("expecting a meta table but got %T", oo[0])
|
||||||
|
|
@ -300,8 +300,13 @@ func hydrate(ns string, oo []runtime.Object, rr render.Rows, re Renderer) error
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Generic interface {
|
||||||
|
SetTable(*metav1beta1.Table)
|
||||||
|
Render(interface{}, string, *render.Row) error
|
||||||
|
}
|
||||||
|
|
||||||
func genericHydrate(ns string, table *metav1beta1.Table, rr render.Rows, re Renderer) error {
|
func genericHydrate(ns string, table *metav1beta1.Table, rr render.Rows, re Renderer) error {
|
||||||
gr, ok := re.(*render.Generic)
|
gr, ok := re.(Generic)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("expecting generic renderer but got %T", re)
|
return fmt.Errorf("expecting generic renderer but got %T", re)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,9 @@ type Component interface {
|
||||||
|
|
||||||
// Renderer represents a resource renderer.
|
// Renderer represents a resource renderer.
|
||||||
type Renderer interface {
|
type Renderer interface {
|
||||||
|
// IsGeneric identifies a generic handler.
|
||||||
|
IsGeneric() bool
|
||||||
|
|
||||||
// Render converts raw resources to tabular data.
|
// Render converts raw resources to tabular data.
|
||||||
Render(o interface{}, ns string, row *render.Row) error
|
Render(o interface{}, ns string, row *render.Row) error
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Alias renders a aliases to screen.
|
// Alias renders a aliases to screen.
|
||||||
type Alias struct{}
|
type Alias struct {
|
||||||
|
Base
|
||||||
// ColorerFunc colors a resource row.
|
|
||||||
func (Alias) ColorerFunc() ColorerFunc {
|
|
||||||
return DefaultColorer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns a header row.
|
// Header returns a header row.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package render
|
||||||
|
|
||||||
|
// DecoratorFunc decorates a string.
|
||||||
|
type DecoratorFunc func(string) string
|
||||||
|
|
||||||
|
// AgeDecorator represents a timestamped as human column.
|
||||||
|
var AgeDecorator = func(a string) string {
|
||||||
|
return toAgeHuman(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Base struct{}
|
||||||
|
|
||||||
|
// IsGeneric identifies a generic handler.
|
||||||
|
func (Base) IsGeneric() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// ColorerFunc colors a resource row.
|
||||||
|
func (Base) ColorerFunc() ColorerFunc {
|
||||||
|
return DefaultColorer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Happy returns true if resource is happy, false otherwise.
|
||||||
|
func (Base) Happy(_ string, _ Row) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
@ -24,7 +24,9 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Benchmark renders a benchmarks to screen.
|
// Benchmark renders a benchmarks to screen.
|
||||||
type Benchmark struct{}
|
type Benchmark struct {
|
||||||
|
Base
|
||||||
|
}
|
||||||
|
|
||||||
// ColorerFunc colors a resource row.
|
// ColorerFunc colors a resource row.
|
||||||
func (b Benchmark) ColorerFunc() ColorerFunc {
|
func (b Benchmark) ColorerFunc() ColorerFunc {
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,9 @@ type ContainerWithMetrics interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Container renders a K8s Container to screen.
|
// Container renders a K8s Container to screen.
|
||||||
type Container struct{}
|
type Container struct {
|
||||||
|
Base
|
||||||
|
}
|
||||||
|
|
||||||
// ColorerFunc colors a resource row.
|
// ColorerFunc colors a resource row.
|
||||||
func (c Container) ColorerFunc() ColorerFunc {
|
func (c Container) ColorerFunc() ColorerFunc {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Context renders a K8s ConfigMap to screen.
|
// Context renders a K8s ConfigMap to screen.
|
||||||
type Context struct{}
|
type Context struct {
|
||||||
|
Base
|
||||||
|
}
|
||||||
|
|
||||||
// ColorerFunc colors a resource row.
|
// ColorerFunc colors a resource row.
|
||||||
func (Context) ColorerFunc() ColorerFunc {
|
func (Context) ColorerFunc() ColorerFunc {
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ClusterRole renders a K8s ClusterRole to screen.
|
// ClusterRole renders a K8s ClusterRole to screen.
|
||||||
type ClusterRole struct{}
|
type ClusterRole struct {
|
||||||
|
Base
|
||||||
// ColorerFunc colors a resource row.
|
|
||||||
func (ClusterRole) ColorerFunc() ColorerFunc {
|
|
||||||
return DefaultColorer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns a header rbw.
|
// Header returns a header rbw.
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ClusterRoleBinding renders a K8s ClusterRoleBinding to screen.
|
// ClusterRoleBinding renders a K8s ClusterRoleBinding to screen.
|
||||||
type ClusterRoleBinding struct{}
|
type ClusterRoleBinding struct {
|
||||||
|
Base
|
||||||
// ColorerFunc colors a resource row.
|
|
||||||
func (ClusterRoleBinding) ColorerFunc() ColorerFunc {
|
|
||||||
return DefaultColorer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns a header rbw.
|
// Header returns a header rbw.
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// CustomResourceDefinition renders a K8s CustomResourceDefinition to screen.
|
// CustomResourceDefinition renders a K8s CustomResourceDefinition to screen.
|
||||||
type CustomResourceDefinition struct{}
|
type CustomResourceDefinition struct {
|
||||||
|
Base
|
||||||
// ColorerFunc colors a resource row.
|
|
||||||
func (CustomResourceDefinition) ColorerFunc() ColorerFunc {
|
|
||||||
return DefaultColorer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns a header rbw.
|
// Header returns a header rbw.
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// CronJob renders a K8s CronJob to screen.
|
// CronJob renders a K8s CronJob to screen.
|
||||||
type CronJob struct{}
|
type CronJob struct {
|
||||||
|
Base
|
||||||
// ColorerFunc colors a resource row.
|
|
||||||
func (CronJob) ColorerFunc() ColorerFunc {
|
|
||||||
return DefaultColorer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns a header row.
|
// Header returns a header row.
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,11 @@ import (
|
||||||
// Dir renders a directory entry to screen.
|
// Dir renders a directory entry to screen.
|
||||||
type Dir struct{}
|
type Dir struct{}
|
||||||
|
|
||||||
|
// IsGeneric identifies a generic handler.
|
||||||
|
func (Dir) IsGeneric() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// ColorerFunc colors a resource row.
|
// ColorerFunc colors a resource row.
|
||||||
func (Dir) ColorerFunc() ColorerFunc {
|
func (Dir) ColorerFunc() ColorerFunc {
|
||||||
return func(ns string, _ Header, re RowEvent) tcell.Color {
|
return func(ns string, _ Header, re RowEvent) tcell.Color {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Deployment renders a K8s Deployment to screen.
|
// Deployment renders a K8s Deployment to screen.
|
||||||
type Deployment struct{}
|
type Deployment struct {
|
||||||
|
Base
|
||||||
|
}
|
||||||
|
|
||||||
// ColorerFunc colors a resource row.
|
// ColorerFunc colors a resource row.
|
||||||
func (d Deployment) ColorerFunc() ColorerFunc {
|
func (d Deployment) ColorerFunc() ColorerFunc {
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// DaemonSet renders a K8s DaemonSet to screen.
|
// DaemonSet renders a K8s DaemonSet to screen.
|
||||||
type DaemonSet struct{}
|
type DaemonSet struct {
|
||||||
|
Base
|
||||||
// ColorerFunc colors a resource row.
|
|
||||||
func (d DaemonSet) ColorerFunc() ColorerFunc {
|
|
||||||
return DefaultColorer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns a header row.
|
// Header returns a header row.
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Endpoints renders a K8s Endpoints to screen.
|
// Endpoints renders a K8s Endpoints to screen.
|
||||||
type Endpoints struct{}
|
type Endpoints struct {
|
||||||
|
Base
|
||||||
// ColorerFunc colors a resource row.
|
|
||||||
func (Endpoints) ColorerFunc() ColorerFunc {
|
|
||||||
return DefaultColorer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns a header row.
|
// Header returns a header row.
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,25 @@
|
||||||
package render
|
package render
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/derailed/k9s/internal/client"
|
||||||
"github.com/gdamore/tcell/v2"
|
"github.com/gdamore/tcell/v2"
|
||||||
|
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BOZO!!
|
|
||||||
// import (
|
|
||||||
// "errors"
|
|
||||||
// "fmt"
|
|
||||||
// "strconv"
|
|
||||||
// "strings"
|
|
||||||
// "time"
|
|
||||||
|
|
||||||
// "github.com/derailed/k9s/internal/client"
|
|
||||||
// "github.com/derailed/tview"
|
|
||||||
// "github.com/gdamore/tcell/v2"
|
|
||||||
// v1 "k8s.io/api/core/v1"
|
|
||||||
// metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
// "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
||||||
// "k8s.io/apimachinery/pkg/runtime"
|
|
||||||
// "k8s.io/apimachinery/pkg/util/duration"
|
|
||||||
// api "k8s.io/kubernetes/pkg/apis/core"
|
|
||||||
// )
|
|
||||||
|
|
||||||
// Event renders a K8s Event to screen.
|
// Event renders a K8s Event to screen.
|
||||||
type Event struct{}
|
type Event struct {
|
||||||
|
Generic
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Event) IsGeneric() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// ColorerFunc colors a resource row.
|
// ColorerFunc colors a resource row.
|
||||||
func (e Event) ColorerFunc() ColorerFunc {
|
func (e *Event) ColorerFunc() ColorerFunc {
|
||||||
return func(ns string, h Header, re RowEvent) tcell.Color {
|
return func(ns string, h Header, re RowEvent) tcell.Color {
|
||||||
if !Happy(ns, h, re.Row) {
|
if !Happy(ns, h, re.Row) {
|
||||||
return ErrColor
|
return ErrColor
|
||||||
|
|
@ -46,128 +36,63 @@ func (e Event) ColorerFunc() ColorerFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// // Header returns a header rbw.
|
var ageCols = map[string]struct{}{
|
||||||
// func (Event) Header(ns string) Header {
|
"FIRST SEEN": {},
|
||||||
// return Header{
|
"LAST SEEN": {},
|
||||||
// HeaderColumn{Name: "NAMESPACE"},
|
}
|
||||||
// HeaderColumn{Name: "LAST SEEN"},
|
|
||||||
// HeaderColumn{Name: "TYPE"},
|
|
||||||
// HeaderColumn{Name: "REASON"},
|
|
||||||
// HeaderColumn{Name: "OBJECT"},
|
|
||||||
// HeaderColumn{Name: "SUBOBJECT"},
|
|
||||||
// HeaderColumn{Name: "SOURCE"},
|
|
||||||
// HeaderColumn{Name: "MESSAGE", Wide: true},
|
|
||||||
// HeaderColumn{Name: "FIRST SEEN", Wide: true},
|
|
||||||
// HeaderColumn{Name: "COUNT", Align: tview.AlignRight},
|
|
||||||
// HeaderColumn{Name: "NAME"},
|
|
||||||
// HeaderColumn{Name: "VALID", Wide: true},
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Render renders a K8s resource to screen.
|
var wideCols = map[string]struct{}{
|
||||||
// func (e Event) Render(o interface{}, ns string, r *Row) error {
|
"SUBOBJECT": {},
|
||||||
// raw, ok := o.(*unstructured.Unstructured)
|
"SOURCE": {},
|
||||||
// if !ok {
|
"FIRST SEEN": {},
|
||||||
// return fmt.Errorf("Expected Event, but got %T", o)
|
"NAME": {},
|
||||||
// }
|
"MESSAGE": {},
|
||||||
// var ev api.Event
|
}
|
||||||
// err := runtime.DefaultUnstructuredConverter.FromUnstructured(raw.Object, &ev)
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// firstTimestamp := translateTimestampSince(ev.FirstTimestamp)
|
func (e *Event) Header(ns string) Header {
|
||||||
// if ev.FirstTimestamp.IsZero() {
|
if e.table == nil {
|
||||||
// firstTimestamp = translateMicroTimestampSince(ev.EventTime)
|
return Header{}
|
||||||
// }
|
}
|
||||||
|
hh := make(Header, 0, len(e.table.ColumnDefinitions))
|
||||||
|
hh = append(hh, HeaderColumn{Name: "NAMESPACE"})
|
||||||
|
for _, h := range e.table.ColumnDefinitions {
|
||||||
|
header := HeaderColumn{Name: strings.ToUpper(h.Name)}
|
||||||
|
if _, ok := ageCols[header.Name]; ok {
|
||||||
|
header.Time = true
|
||||||
|
}
|
||||||
|
if _, ok := wideCols[header.Name]; ok {
|
||||||
|
header.Wide = true
|
||||||
|
}
|
||||||
|
hh = append(hh, header)
|
||||||
|
}
|
||||||
|
|
||||||
// lastTimestamp := translateTimestampSince(ev.LastTimestamp)
|
return hh
|
||||||
// if ev.LastTimestamp.IsZero() {
|
}
|
||||||
// lastTimestamp = firstTimestamp
|
|
||||||
// }
|
|
||||||
// count := ev.Count
|
|
||||||
// if ev.Series != nil {
|
|
||||||
// lastTimestamp = translateMicroTimestampSince(ev.Series.LastObservedTime)
|
|
||||||
// count = ev.Series.Count
|
|
||||||
// } else if count == 0 {
|
|
||||||
// // Singleton events don't have a count set in the new API.
|
|
||||||
// count = 1
|
|
||||||
// }
|
|
||||||
|
|
||||||
// var target string
|
// Render renders a K8s resource to screen.
|
||||||
// if len(ev.InvolvedObject.Name) > 0 {
|
func (e *Event) Render(o interface{}, ns string, r *Row) error {
|
||||||
// target = fmt.Sprintf("%s/%s", strings.ToLower(ev.InvolvedObject.Kind), ev.InvolvedObject.Name)
|
row, ok := o.(metav1beta1.TableRow)
|
||||||
// } else {
|
if !ok {
|
||||||
// target = strings.ToLower(ev.InvolvedObject.Kind)
|
return fmt.Errorf("expecting a TableRow but got %T", o)
|
||||||
// }
|
}
|
||||||
|
nns, name, err := resourceNS(row.Object.Raw)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// r.ID = client.MetaFQN(ev.ObjectMeta)
|
if !ok {
|
||||||
// r.Fields = Fields{
|
return fmt.Errorf("expecting row 0 to be a string but got %T", row.Cells[0])
|
||||||
// ev.Namespace,
|
}
|
||||||
// lastTimestamp,
|
r.ID = client.FQN(nns, name)
|
||||||
// ev.Type,
|
r.Fields = make(Fields, 0, len(e.Header(ns)))
|
||||||
// ev.Reason,
|
r.Fields = append(r.Fields, nns)
|
||||||
// target,
|
for _, c := range row.Cells {
|
||||||
// ev.InvolvedObject.FieldPath,
|
if c == nil {
|
||||||
// fmtEventSource(ev.Source, ev.ReportingController, ev.ReportingInstance),
|
r.Fields = append(r.Fields, Blank)
|
||||||
// strings.TrimSpace(ev.Message),
|
continue
|
||||||
// firstTimestamp,
|
}
|
||||||
// strconv.Itoa(int(count)),
|
r.Fields = append(r.Fields, fmt.Sprintf("%v", c))
|
||||||
// ev.Name,
|
}
|
||||||
// asStatus(e.diagnose(ev.Type)),
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return nil
|
return nil
|
||||||
// }
|
}
|
||||||
|
|
||||||
// func translateMicroTimestampSince(timestamp metav1.MicroTime) string {
|
|
||||||
// if timestamp.IsZero() {
|
|
||||||
// return "<unknown>"
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return duration.HumanDuration(time.Since(timestamp.Time))
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func translateTimestampSince(timestamp metav1.Time) string {
|
|
||||||
// if timestamp.IsZero() {
|
|
||||||
// return "<unknown>"
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return duration.HumanDuration(time.Since(timestamp.Time))
|
|
||||||
// }
|
|
||||||
// func fmtEventSource(es api.EventSource, reportingController, reportingInstance string) string {
|
|
||||||
// return fmtEventSourceComponentInstance(
|
|
||||||
// firstNonEmpty(es.Component, reportingController),
|
|
||||||
// firstNonEmpty(es.Host, reportingInstance),
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func fmtEventSourceComponentInstance(component, instance string) string {
|
|
||||||
// if len(instance) == 0 {
|
|
||||||
// return component
|
|
||||||
// }
|
|
||||||
// return component + ", " + instance
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func firstNonEmpty(ss ...string) string {
|
|
||||||
// for _, s := range ss {
|
|
||||||
// if len(s) > 0 {
|
|
||||||
// return s
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return ""
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Happy returns true if resource is happy, false otherwise.
|
|
||||||
// func (Event) diagnose(kind string) error {
|
|
||||||
// if kind != "Normal" {
|
|
||||||
// return errors.New("failed event")
|
|
||||||
// }
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Helpers...
|
|
||||||
|
|
||||||
// func asRef(r v1.ObjectReference) string {
|
|
||||||
// return strings.ToLower(r.Kind) + ":" + r.Name
|
|
||||||
// }
|
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,13 @@ const ageTableCol = "Age"
|
||||||
|
|
||||||
// Generic renders a generic resource to screen.
|
// Generic renders a generic resource to screen.
|
||||||
type Generic struct {
|
type Generic struct {
|
||||||
|
Base
|
||||||
table *metav1beta1.Table
|
table *metav1beta1.Table
|
||||||
|
|
||||||
ageIndex int
|
ageIndex int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Happy returns true if resource is happy, false otherwise.
|
func (*Generic) IsGeneric() bool {
|
||||||
func (Generic) Happy(ns string, r Row) bool {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -30,7 +30,7 @@ func (g *Generic) SetTable(t *metav1beta1.Table) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ColorerFunc colors a resource row.
|
// ColorerFunc colors a resource row.
|
||||||
func (Generic) ColorerFunc() ColorerFunc {
|
func (*Generic) ColorerFunc() ColorerFunc {
|
||||||
return DefaultColorer
|
return DefaultColorer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,11 @@ import (
|
||||||
// Helm renders a helm chart to screen.
|
// Helm renders a helm chart to screen.
|
||||||
type Helm struct{}
|
type Helm struct{}
|
||||||
|
|
||||||
|
// IsGeneric identifies a generic handler.
|
||||||
|
func (Helm) IsGeneric() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// ColorerFunc colors a resource row.
|
// ColorerFunc colors a resource row.
|
||||||
func (Helm) ColorerFunc() ColorerFunc {
|
func (Helm) ColorerFunc() ColorerFunc {
|
||||||
return func(ns string, h Header, re RowEvent) tcell.Color {
|
return func(ns string, h Header, re RowEvent) tcell.Color {
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// HorizontalPodAutoscaler renders a K8s HorizontalPodAutoscaler to screen.
|
// HorizontalPodAutoscaler renders a K8s HorizontalPodAutoscaler to screen.
|
||||||
type HorizontalPodAutoscaler struct{}
|
type HorizontalPodAutoscaler struct {
|
||||||
|
Base
|
||||||
// ColorerFunc colors a resource row.
|
|
||||||
func (HorizontalPodAutoscaler) ColorerFunc() ColorerFunc {
|
|
||||||
return DefaultColorer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns a header row.
|
// Header returns a header row.
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Job renders a K8s Job to screen.
|
// Job renders a K8s Job to screen.
|
||||||
type Job struct{}
|
type Job struct {
|
||||||
|
Base
|
||||||
// ColorerFunc colors a resource row.
|
|
||||||
func (Job) ColorerFunc() ColorerFunc {
|
|
||||||
return DefaultColorer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns a header row.
|
// Header returns a header row.
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,8 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Node renders a K8s Node to screen.
|
// Node renders a K8s Node to screen.
|
||||||
type Node struct{}
|
type Node struct {
|
||||||
|
Base
|
||||||
// ColorerFunc colors a resource row.
|
|
||||||
func (n Node) ColorerFunc() ColorerFunc {
|
|
||||||
return DefaultColorer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns a header row.
|
// Header returns a header row.
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// NetworkPolicy renders a K8s NetworkPolicy to screen.
|
// NetworkPolicy renders a K8s NetworkPolicy to screen.
|
||||||
type NetworkPolicy struct{}
|
type NetworkPolicy struct {
|
||||||
|
Base
|
||||||
// ColorerFunc colors a resource row.
|
|
||||||
func (NetworkPolicy) ColorerFunc() ColorerFunc {
|
|
||||||
return DefaultColorer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns a header row.
|
// Header returns a header row.
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Namespace renders a K8s Namespace to screen.
|
// Namespace renders a K8s Namespace to screen.
|
||||||
type Namespace struct{}
|
type Namespace struct {
|
||||||
|
Base
|
||||||
|
}
|
||||||
|
|
||||||
// ColorerFunc colors a resource row.
|
// ColorerFunc colors a resource row.
|
||||||
func (n Namespace) ColorerFunc() ColorerFunc {
|
func (n Namespace) ColorerFunc() ColorerFunc {
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// PodDisruptionBudget renders a K8s PodDisruptionBudget to screen.
|
// PodDisruptionBudget renders a K8s PodDisruptionBudget to screen.
|
||||||
type PodDisruptionBudget struct{}
|
type PodDisruptionBudget struct {
|
||||||
|
Base
|
||||||
// ColorerFunc colors a resource row.
|
|
||||||
func (p PodDisruptionBudget) ColorerFunc() ColorerFunc {
|
|
||||||
return DefaultColorer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns a header row.
|
// Header returns a header row.
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Pod renders a K8s Pod to screen.
|
// Pod renders a K8s Pod to screen.
|
||||||
type Pod struct{}
|
type Pod struct {
|
||||||
|
Base
|
||||||
|
}
|
||||||
|
|
||||||
// ColorerFunc colors a resource row.
|
// ColorerFunc colors a resource row.
|
||||||
func (p Pod) ColorerFunc() ColorerFunc {
|
func (p Pod) ColorerFunc() ColorerFunc {
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,9 @@ func rbacVerbHeader() Header {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Policy renders a rbac policy to screen.
|
// Policy renders a rbac policy to screen.
|
||||||
type Policy struct{}
|
type Policy struct {
|
||||||
|
Base
|
||||||
|
}
|
||||||
|
|
||||||
// ColorerFunc colors a resource row.
|
// ColorerFunc colors a resource row.
|
||||||
func (Policy) ColorerFunc() ColorerFunc {
|
func (Policy) ColorerFunc() ColorerFunc {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Popeye renders a sanitizer to screen.
|
// Popeye renders a sanitizer to screen.
|
||||||
type Popeye struct{}
|
type Popeye struct {
|
||||||
|
Base
|
||||||
|
}
|
||||||
|
|
||||||
// ColorerFunc colors a resource row.
|
// ColorerFunc colors a resource row.
|
||||||
func (Popeye) ColorerFunc() ColorerFunc {
|
func (Popeye) ColorerFunc() ColorerFunc {
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,9 @@ type Forwarder interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// PortForward renders a portforwards to screen.
|
// PortForward renders a portforwards to screen.
|
||||||
type PortForward struct{}
|
type PortForward struct {
|
||||||
|
Base
|
||||||
|
}
|
||||||
|
|
||||||
// ColorerFunc colors a resource row.
|
// ColorerFunc colors a resource row.
|
||||||
func (PortForward) ColorerFunc() ColorerFunc {
|
func (PortForward) ColorerFunc() ColorerFunc {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// PersistentVolume renders a K8s PersistentVolume to screen.
|
// PersistentVolume renders a K8s PersistentVolume to screen.
|
||||||
type PersistentVolume struct{}
|
type PersistentVolume struct {
|
||||||
|
Base
|
||||||
|
}
|
||||||
|
|
||||||
// ColorerFunc colors a resource row.
|
// ColorerFunc colors a resource row.
|
||||||
func (p PersistentVolume) ColorerFunc() ColorerFunc {
|
func (p PersistentVolume) ColorerFunc() ColorerFunc {
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// PersistentVolumeClaim renders a K8s PersistentVolumeClaim to screen.
|
// PersistentVolumeClaim renders a K8s PersistentVolumeClaim to screen.
|
||||||
type PersistentVolumeClaim struct{}
|
type PersistentVolumeClaim struct {
|
||||||
|
Base
|
||||||
// ColorerFunc colors a resource row.
|
|
||||||
func (p PersistentVolumeClaim) ColorerFunc() ColorerFunc {
|
|
||||||
return DefaultColorer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns a header rbw.
|
// Header returns a header rbw.
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,9 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Rbac renders a rbac to screen.
|
// Rbac renders a rbac to screen.
|
||||||
type Rbac struct{}
|
type Rbac struct {
|
||||||
|
Base
|
||||||
|
}
|
||||||
|
|
||||||
// ColorerFunc colors a resource row.
|
// ColorerFunc colors a resource row.
|
||||||
func (Rbac) ColorerFunc() ColorerFunc {
|
func (Rbac) ColorerFunc() ColorerFunc {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reference renders a reference to screen.
|
// Reference renders a reference to screen.
|
||||||
type Reference struct{}
|
type Reference struct {
|
||||||
|
Base
|
||||||
|
}
|
||||||
|
|
||||||
// ColorerFunc colors a resource row.
|
// ColorerFunc colors a resource row.
|
||||||
func (Reference) ColorerFunc() ColorerFunc {
|
func (Reference) ColorerFunc() ColorerFunc {
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Role renders a K8s Role to screen.
|
// Role renders a K8s Role to screen.
|
||||||
type Role struct{}
|
type Role struct {
|
||||||
|
Base
|
||||||
// ColorerFunc colors a resource row.
|
|
||||||
func (Role) ColorerFunc() ColorerFunc {
|
|
||||||
return DefaultColorer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns a header row.
|
// Header returns a header row.
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// RoleBinding renders a K8s RoleBinding to screen.
|
// RoleBinding renders a K8s RoleBinding to screen.
|
||||||
type RoleBinding struct{}
|
type RoleBinding struct {
|
||||||
|
Base
|
||||||
// ColorerFunc colors a resource row.
|
|
||||||
func (RoleBinding) ColorerFunc() ColorerFunc {
|
|
||||||
return DefaultColorer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns a header rbw.
|
// Header returns a header rbw.
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ReplicaSet renders a K8s ReplicaSet to screen.
|
// ReplicaSet renders a K8s ReplicaSet to screen.
|
||||||
type ReplicaSet struct{}
|
type ReplicaSet struct {
|
||||||
|
Base
|
||||||
|
}
|
||||||
|
|
||||||
// ColorerFunc colors a resource row.
|
// ColorerFunc colors a resource row.
|
||||||
func (r ReplicaSet) ColorerFunc() ColorerFunc {
|
func (r ReplicaSet) ColorerFunc() ColorerFunc {
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ServiceAccount renders a K8s ServiceAccount to screen.
|
// ServiceAccount renders a K8s ServiceAccount to screen.
|
||||||
type ServiceAccount struct{}
|
type ServiceAccount struct {
|
||||||
|
Base
|
||||||
// ColorerFunc colors a resource row.
|
|
||||||
func (ServiceAccount) ColorerFunc() ColorerFunc {
|
|
||||||
return DefaultColorer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns a header row.
|
// Header returns a header row.
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// StorageClass renders a K8s StorageClass to screen.
|
// StorageClass renders a K8s StorageClass to screen.
|
||||||
type StorageClass struct{}
|
type StorageClass struct {
|
||||||
|
Base
|
||||||
// ColorerFunc colors a resource row.
|
|
||||||
func (StorageClass) ColorerFunc() ColorerFunc {
|
|
||||||
return DefaultColorer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns a header row.
|
// Header returns a header row.
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ScreenDump renders a screendumps to screen.
|
// ScreenDump renders a screendumps to screen.
|
||||||
type ScreenDump struct{}
|
type ScreenDump struct {
|
||||||
|
Base
|
||||||
|
}
|
||||||
|
|
||||||
// ColorerFunc colors a resource row.
|
// ColorerFunc colors a resource row.
|
||||||
func (ScreenDump) ColorerFunc() ColorerFunc {
|
func (ScreenDump) ColorerFunc() ColorerFunc {
|
||||||
|
|
@ -21,14 +23,6 @@ func (ScreenDump) ColorerFunc() ColorerFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecoratorFunc decorates a string.
|
|
||||||
type DecoratorFunc func(string) string
|
|
||||||
|
|
||||||
// AgeDecorator represents a timestamped as human column.
|
|
||||||
var AgeDecorator = func(a string) string {
|
|
||||||
return toAgeHuman(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Header returns a header row.
|
// Header returns a header row.
|
||||||
func (ScreenDump) Header(ns string) Header {
|
func (ScreenDump) Header(ns string) Header {
|
||||||
return Header{
|
return Header{
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// StatefulSet renders a K8s StatefulSet to screen.
|
// StatefulSet renders a K8s StatefulSet to screen.
|
||||||
type StatefulSet struct{}
|
type StatefulSet struct {
|
||||||
|
Base
|
||||||
// ColorerFunc colors a resource row.
|
|
||||||
func (s StatefulSet) ColorerFunc() ColorerFunc {
|
|
||||||
return DefaultColorer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns a header row.
|
// Header returns a header row.
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Subject renders a rbac to screen.
|
// Subject renders a rbac to screen.
|
||||||
type Subject struct{}
|
type Subject struct {
|
||||||
|
Base
|
||||||
// Happy returns true if resource is happy, false otherwise.
|
|
||||||
func (Subject) Happy(_ string, _ Row) bool {
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ColorerFunc colors a resource row.
|
// ColorerFunc colors a resource row.
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Service renders a K8s Service to screen.
|
// Service renders a K8s Service to screen.
|
||||||
type Service struct{}
|
type Service struct {
|
||||||
|
Base
|
||||||
// ColorerFunc colors a resource row.
|
|
||||||
func (Service) ColorerFunc() ColorerFunc {
|
|
||||||
return DefaultColorer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns a header row.
|
// Header returns a header row.
|
||||||
|
|
|
||||||
|
|
@ -88,8 +88,8 @@ func (k ks) CurrentNamespaceName() (string, error) {
|
||||||
return "test", nil
|
return "test", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k ks) ClusterNames() ([]string, error) {
|
func (k ks) ClusterNames() (map[string]struct{}, error) {
|
||||||
return []string{"test"}, nil
|
return map[string]struct{}{"test": {}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k ks) NamespaceNames(nn []v1.Namespace) []string {
|
func (k ks) NamespaceNames(nn []v1.Namespace) []string {
|
||||||
|
|
|
||||||
|
|
@ -276,10 +276,10 @@ func (a *App) Resume() {
|
||||||
|
|
||||||
go a.clusterUpdater(ctx)
|
go a.clusterUpdater(ctx)
|
||||||
if err := a.StylesWatcher(ctx, a); err != nil {
|
if err := a.StylesWatcher(ctx, a); err != nil {
|
||||||
log.Error().Err(err).Msgf("Styles watcher failed")
|
log.Warn().Err(err).Msgf("Styles watcher failed")
|
||||||
}
|
}
|
||||||
if err := a.CustomViewsWatcher(ctx, a); err != nil {
|
if err := a.CustomViewsWatcher(ctx, a); err != nil {
|
||||||
log.Error().Err(err).Msgf("CustomView watcher failed")
|
log.Warn().Err(err).Msgf("CustomView watcher failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -357,6 +357,10 @@ func (a *App) switchNS(ns string) error {
|
||||||
if ns == client.ClusterScope {
|
if ns == client.ClusterScope {
|
||||||
ns = client.AllNamespaces
|
ns = client.AllNamespaces
|
||||||
}
|
}
|
||||||
|
if ns == a.Config.ActiveNamespace() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
ok, err := a.isValidNS(ns)
|
ok, err := a.isValidNS(ns)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -365,7 +369,10 @@ func (a *App) switchNS(ns string) error {
|
||||||
return fmt.Errorf("Invalid namespace %q", ns)
|
return fmt.Errorf("Invalid namespace %q", ns)
|
||||||
}
|
}
|
||||||
if err := a.Config.SetActiveNamespace(ns); err != nil {
|
if err := a.Config.SetActiveNamespace(ns); err != nil {
|
||||||
return fmt.Errorf("Unable to save active namespace in config")
|
return err
|
||||||
|
}
|
||||||
|
if err := a.Config.Save(); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return a.factory.SetActiveNS(ns)
|
return a.factory.SetActiveNS(ns)
|
||||||
|
|
|
||||||
|
|
@ -134,9 +134,6 @@ func (b *Browser) Start() {
|
||||||
if err := b.app.switchNS(ns); err != nil {
|
if err := b.app.switchNS(ns); err != nil {
|
||||||
log.Error().Err(err).Msgf("ns switch failed")
|
log.Error().Err(err).Msgf("ns switch failed")
|
||||||
}
|
}
|
||||||
if err := b.app.Config.Save(); err != nil {
|
|
||||||
log.Error().Err(err).Msgf("Config Save")
|
|
||||||
}
|
|
||||||
|
|
||||||
b.Stop()
|
b.Stop()
|
||||||
b.GetModel().AddListener(b)
|
b.GetModel().AddListener(b)
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,8 @@ func NewEvent(gvr client.GVR) ResourceViewer {
|
||||||
e := Event{
|
e := Event{
|
||||||
ResourceViewer: NewBrowser(gvr),
|
ResourceViewer: NewBrowser(gvr),
|
||||||
}
|
}
|
||||||
e.GetTable().SetColorerFn(render.Event{}.ColorerFunc())
|
var r *render.Event
|
||||||
|
e.GetTable().SetColorerFn(r.ColorerFunc())
|
||||||
e.AddBindKeysFn(e.bindKeys)
|
e.AddBindKeysFn(e.bindKeys)
|
||||||
e.GetTable().SetSortCol("LAST SEEN", false)
|
e.GetTable().SetSortCol("LAST SEEN", false)
|
||||||
|
|
||||||
|
|
@ -25,9 +26,10 @@ func NewEvent(gvr client.GVR) ResourceViewer {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Event) bindKeys(aa ui.KeyActions) {
|
func (e *Event) bindKeys(aa ui.KeyActions) {
|
||||||
aa.Delete(tcell.KeyCtrlD, ui.KeyE)
|
aa.Delete(tcell.KeyCtrlD, ui.KeyE, ui.KeyA)
|
||||||
aa.Add(ui.KeyActions{
|
aa.Add(ui.KeyActions{
|
||||||
ui.KeyShiftL: ui.NewKeyAction("Sort LastSeen", e.GetTable().SortColCmd("LAST SEEN", false), false),
|
ui.KeyShiftL: ui.NewKeyAction("Sort LastSeen", e.GetTable().SortColCmd("LAST SEEN", false), false),
|
||||||
|
ui.KeyShiftF: ui.NewKeyAction("Sort FirstSeen", e.GetTable().SortColCmd("FIRST SEEN", false), false),
|
||||||
ui.KeyShiftT: ui.NewKeyAction("Sort Type", e.GetTable().SortColCmd("TYPE", true), false),
|
ui.KeyShiftT: ui.NewKeyAction("Sort Type", e.GetTable().SortColCmd("TYPE", true), false),
|
||||||
ui.KeyShiftR: ui.NewKeyAction("Sort Reason", e.GetTable().SortColCmd("REASON", true), false),
|
ui.KeyShiftR: ui.NewKeyAction("Sort Reason", e.GetTable().SortColCmd("REASON", true), false),
|
||||||
ui.KeyShiftS: ui.NewKeyAction("Sort Source", e.GetTable().SortColCmd("SOURCE", true), false),
|
ui.KeyShiftS: ui.NewKeyAction("Sort Source", e.GetTable().SortColCmd("SOURCE", true), false),
|
||||||
|
|
|
||||||
|
|
@ -171,8 +171,8 @@ func (k ks) CurrentNamespaceName() (string, error) {
|
||||||
return "test", nil
|
return "test", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k ks) ClusterNames() ([]string, error) {
|
func (k ks) ClusterNames() (map[string]struct{}, error) {
|
||||||
return []string{"test"}, nil
|
return map[string]struct{}{"test": {}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k ks) NamespaceNames(nn []v1.Namespace) []string {
|
func (k ks) NamespaceNames(nn []v1.Namespace) []string {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Section represents an xray renderer.
|
// Section represents an xray renderer.
|
||||||
type Section struct{}
|
type Section struct {
|
||||||
|
render.Base
|
||||||
|
}
|
||||||
|
|
||||||
// Render renders an xray node.
|
// Render renders an xray node.
|
||||||
func (s *Section) Render(ctx context.Context, ns string, o interface{}) error {
|
func (s *Section) Render(ctx context.Context, ns string, o interface{}) error {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue