worked on logs + ansi support + bugs

mine
derailed 2019-03-09 17:46:25 -07:00
parent 0b0a723c68
commit f0a0c8f06d
56 changed files with 296 additions and 229 deletions

View File

@ -141,10 +141,11 @@ K9s uses aliases to navigate most K8s resources.
## Known Issues ## Known Issues
This initial drop is brittle. K9s will most likely blow up if... This initial drop is brittle. K9s will most likely blow up...
1. You're running older versions of Kubernetes. K9s works best Kubernetes 1.10+
1. You don't have enough RBAC fu to manage your cluster 1. You don't have enough RBAC fu to manage your cluster
2. Your cluster does not run a metric server. 1. Your cluster does not run a metric server.
--- ---

View File

@ -0,0 +1,26 @@
# Release v0.2.2
## Notes
Thank you to all that contributed with flushing out issues with 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.
Thank you so much for your support!!
---
## Change Logs
+ [Feature #98](https://github.com/derailed/k9s/issues/98) Pod view with node name.
+ [Feature #29](https://github.com/derailed/k9s/issues/29) Support ANSI colors in logs.
+ [Feature #105](https://github.com/derailed/k9s/issues/29) [Experimental] Add support for manual refresh.
---
## Resolved Bugs
+ [Issue #102](https://github.com/derailed/k9s/issues/102)
+ [Issue #104](https://github.com/derailed/k9s/issues/104)

3
go.mod
View File

@ -23,7 +23,8 @@ require (
github.com/onsi/gomega v1.4.3 // indirect github.com/onsi/gomega v1.4.3 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/petergtz/pegomock v0.0.0-20181206220228-b113d17a7e81 github.com/petergtz/pegomock v0.0.0-20181206220228-b113d17a7e81
github.com/sirupsen/logrus v1.3.0 github.com/rs/zerolog v1.12.0
github.com/sirupsen/logrus v1.3.0 // indirect
github.com/spf13/cobra v0.0.3 github.com/spf13/cobra v0.0.3
github.com/spf13/pflag v1.0.3 // indirect github.com/spf13/pflag v1.0.3 // indirect
github.com/stretchr/testify v1.2.2 github.com/stretchr/testify v1.2.2

2
go.sum
View File

@ -98,6 +98,8 @@ github.com/prometheus/common v0.0.0-20181218105931-67670fe90761/go.mod h1:daVV7q
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/rivo/tview v0.0.0-20190213202703-b373355e9db4/go.mod h1:J4W+hErFfITUbyFAEXizpmkuxX7ZN56dopxHB4XQhMw= github.com/rivo/tview v0.0.0-20190213202703-b373355e9db4/go.mod h1:J4W+hErFfITUbyFAEXizpmkuxX7ZN56dopxHB4XQhMw=
github.com/rs/zerolog v1.12.0 h1:aqZ1XRadoS8IBknR5IDFvGzbHly1X9ApIqOroooQF/c=
github.com/rs/zerolog v1.12.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
github.com/sirupsen/logrus v1.3.0 h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME= github.com/sirupsen/logrus v1.3.0 h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME=
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=

View File

@ -7,7 +7,8 @@ import (
"github.com/derailed/k9s/internal/config" "github.com/derailed/k9s/internal/config"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
"github.com/derailed/k9s/internal/views" "github.com/derailed/k9s/internal/views"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
) )
@ -55,7 +56,7 @@ func init() {
} }
func initK9s() { func initK9s() {
log.Info("🐶 K9s starting up...") log.Info().Msg("🐶 K9s starting up...")
// Load K9s config file... // Load K9s config file...
cfg := k8s.NewConfig(k8sFlags) cfg := k8s.NewConfig(k8sFlags)
@ -64,14 +65,14 @@ func initK9s() {
// Init K8s connection... // Init K8s connection...
k8s.InitConnectionOrDie(cfg) k8s.InitConnectionOrDie(cfg)
log.Info("✅ Kubernetes connectivity") log.Info().Msg("✅ Kubernetes connectivity")
config.Root.Save() config.Root.Save()
} }
func initK9sConfig() { func initK9sConfig() {
if err := config.Root.Load(config.K9sConfigFile); err != nil { if err := config.Root.Load(config.K9sConfigFile); err != nil {
log.Warnf("Unable to locate K9s config. Generating new configuration...") log.Warn().Msg("Unable to locate K9s config. Generating new configuration...")
} }
config.Root.K9s.RefreshRate = refreshRate config.Root.K9s.RefreshRate = refreshRate
@ -93,7 +94,7 @@ func initK9sConfig() {
config.Root.SetActiveNamespace(cfg.Contexts[ctx].Namespace) config.Root.SetActiveNamespace(cfg.Contexts[ctx].Namespace)
} }
} }
log.Debugf("Active Context `%v`", ctx) log.Debug().Msgf("Active Context `%v`", ctx)
if isSet(k8sFlags.Namespace) { if isSet(k8sFlags.Namespace) {
config.Root.SetActiveNamespace(*k8sFlags.Namespace) config.Root.SetActiveNamespace(*k8sFlags.Namespace)
@ -120,16 +121,27 @@ func isSet(s *string) bool {
// Execute root command // Execute root command
func Execute() { func Execute() {
if err := rootCmd.Execute(); err != nil { if err := rootCmd.Execute(); err != nil {
log.Panic(err) log.Panic().Err(err)
}
}
func parseLevel(level string) zerolog.Level {
switch level {
case "debug":
return zerolog.DebugLevel
case "warn":
return zerolog.WarnLevel
case "error":
return zerolog.ErrorLevel
case "fatal":
return zerolog.FatalLevel
default:
return zerolog.InfoLevel
} }
} }
func run(cmd *cobra.Command, args []string) { func run(cmd *cobra.Command, args []string) {
level, err := log.ParseLevel(logLevel) zerolog.SetGlobalLevel(parseLevel(logLevel))
if err != nil {
level = log.DebugLevel
}
log.SetLevel(level)
initK9s() initK9s()
@ -140,7 +152,7 @@ func run(cmd *cobra.Command, args []string) {
clearScreen() clearScreen()
if err := recover(); err != nil { if err := recover(); err != nil {
app.Stop() app.Stop()
fmt.Println(err) log.Error().Msgf("Boom! %#v", err)
debug.PrintStack() debug.PrintStack()
} }
}() }()

View File

@ -10,7 +10,7 @@ import (
"path/filepath" "path/filepath"
"github.com/derailed/k9s/internal/resource" "github.com/derailed/k9s/internal/resource"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
@ -76,11 +76,11 @@ func (c *Config) FavNamespaces() []string {
// SetActiveNamespace set the active namespace in the current cluster. // SetActiveNamespace set the active namespace in the current cluster.
func (c *Config) SetActiveNamespace(ns string) error { func (c *Config) SetActiveNamespace(ns string) error {
log.Debugf("Setting active namespace `%s", ns) log.Debug().Msgf("Setting active namespace `%s", ns)
if c.K9s.ActiveCluster() != nil { if c.K9s.ActiveCluster() != nil {
return c.K9s.ActiveCluster().Namespace.SetActive(ns, c.settings) return c.K9s.ActiveCluster().Namespace.SetActive(ns, c.settings)
} }
log.Error("Doh! no active cluster. unable to set active namespace") log.Error().Msg("Doh! no active cluster. unable to set active namespace")
return fmt.Errorf("no active cluster. unable to set active namespace") return fmt.Errorf("no active cluster. unable to set active namespace")
} }
@ -117,7 +117,7 @@ func (c *Config) Load(path string) error {
// Save configuration to disk. // Save configuration to disk.
func (c *Config) Save() error { func (c *Config) Save() error {
log.Debugf("[Config] Saving configuration...") log.Debug().Msg("[Config] Saving configuration...")
c.Validate() c.Validate()
return c.SaveFile(K9sConfigFile) return c.SaveFile(K9sConfigFile)
} }
@ -127,7 +127,7 @@ func (c *Config) SaveFile(path string) error {
EnsurePath(path, DefaultDirMod) EnsurePath(path, DefaultDirMod)
cfg, err := yaml.Marshal(c) cfg, err := yaml.Marshal(c)
if err != nil { if err != nil {
log.Errorf("[Config] Unable to save K9s config file: %v", err) log.Error().Msgf("[Config] Unable to save K9s config file: %v", err)
return err return err
} }
return ioutil.WriteFile(path, cfg, 0644) return ioutil.WriteFile(path, cfg, 0644)
@ -140,9 +140,9 @@ func (c *Config) Validate() {
// Dump debug... // Dump debug...
func (c *Config) Dump(msg string) { func (c *Config) Dump(msg string) {
log.Debug(msg) log.Debug().Msg(msg)
log.Debugf("Current Context: %s\n", c.K9s.CurrentCluster) log.Debug().Msgf("Current Context: %s\n", c.K9s.CurrentCluster)
for k, cl := range c.K9s.Clusters { for k, cl := range c.K9s.Clusters {
log.Debugf("K9s cluster: %s -- %s\n", k, cl.Namespace) log.Debug().Msgf("K9s cluster: %s -- %s\n", k, cl.Namespace)
} }
} }

View File

@ -8,9 +8,14 @@ import (
"github.com/derailed/k9s/internal/config" "github.com/derailed/k9s/internal/config"
m "github.com/petergtz/pegomock" m "github.com/petergtz/pegomock"
"github.com/rs/zerolog"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func init() {
zerolog.SetGlobalLevel(zerolog.FatalLevel)
}
func TestConfigValidate(t *testing.T) { func TestConfigValidate(t *testing.T) {
setup(t) setup(t)

View File

@ -5,7 +5,7 @@ import (
"os/user" "os/user"
"path/filepath" "path/filepath"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
) )
@ -56,7 +56,7 @@ func EnsurePath(path string, mod os.FileMode) {
dir := filepath.Dir(path) dir := filepath.Dir(path)
if _, err := os.Stat(dir); os.IsNotExist(err) { if _, err := os.Stat(dir); os.IsNotExist(err) {
if err = os.Mkdir(dir, mod); err != nil { if err = os.Mkdir(dir, mod); err != nil {
log.Errorf("Unable to create K9s home config dir: %v", err) log.Error().Msgf("Unable to create K9s home config dir: %v", err)
panic(err) panic(err)
} }
} }

View File

@ -1,7 +1,7 @@
package config package config
import ( import (
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
) )
const ( const (
@ -27,20 +27,20 @@ func NewNamespace() *Namespace {
// Validate a namespace is setup correctly // Validate a namespace is setup correctly
func (n *Namespace) Validate(ks KubeSettings) { func (n *Namespace) Validate(ks KubeSettings) {
log.Debug("Validating favorites...", n.Active) log.Debug().Msgf("Validating favorites... %s", n.Active)
nn, err := ks.NamespaceNames() nn, err := ks.NamespaceNames()
if err != nil { if err != nil {
return return
} }
if !n.isAllNamespace() && !InList(nn, n.Active) { if !n.isAllNamespace() && !InList(nn, n.Active) {
log.Debugf("[Config] Validation error active namespace resetting to `default") log.Debug().Msg("[Config] Validation error active namespace resetting to `default")
n.Active = defaultNS n.Active = defaultNS
} }
for _, ns := range n.Favorites { for _, ns := range n.Favorites {
if ns != allNS && !InList(nn, ns) { if ns != allNS && !InList(nn, ns) {
log.Debugf("[Config] Invalid favorite found '%s' - %t", ns, n.isAllNamespace()) log.Debug().Msgf("[Config] Invalid favorite found '%s' - %t", ns, n.isAllNamespace())
n.rmFavNS(ns) n.rmFavNS(ns)
} }
} }
@ -48,7 +48,7 @@ func (n *Namespace) Validate(ks KubeSettings) {
// SetActive set the active namespace. // SetActive set the active namespace.
func (n *Namespace) SetActive(ns string, ks KubeSettings) error { func (n *Namespace) SetActive(ns string, ks KubeSettings) error {
log.Debug("Setting active ns ", ns) log.Debug().Msgf("Setting active ns %s", ns)
n.Active = ns n.Active = ns
n.addFavNS(ns) n.addFavNS(ns)
return nil return nil

View File

@ -4,7 +4,7 @@ import (
"errors" "errors"
"fmt" "fmt"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
@ -239,7 +239,7 @@ func (c *Config) ConfigAccess() (clientcmd.ConfigAccess, error) {
// RawConfig fetch the current kubeconfig with no overrides. // RawConfig fetch the current kubeconfig with no overrides.
func (c *Config) RawConfig() (clientcmdapi.Config, error) { func (c *Config) RawConfig() (clientcmdapi.Config, error) {
if c.rawConfig != nil && c.rawConfig.CurrentContext != c.currentContext { if c.rawConfig != nil && c.rawConfig.CurrentContext != c.currentContext {
log.Debugf("Context swith detected...") log.Debug().Msg("Context swith detected...")
c.currentContext = c.rawConfig.CurrentContext c.currentContext = c.rawConfig.CurrentContext
c.reset() c.reset()
} }
@ -248,7 +248,7 @@ func (c *Config) RawConfig() (clientcmdapi.Config, error) {
if err := c.configFromFlags(); err != nil { if err := c.configFromFlags(); err != nil {
return clientcmdapi.Config{}, err return clientcmdapi.Config{}, err
} }
log.Debugf("Reloading RawConfig...") log.Debug().Msg("Reloading RawConfig...")
cfg, err := c.clientConfig.RawConfig() cfg, err := c.clientConfig.RawConfig()
if err != nil { if err != nil {
return cfg, err return cfg, err
@ -269,7 +269,7 @@ func (c *Config) RESTConfig() (*restclient.Config, error) {
if err != nil { if err != nil {
return c.restConfig, err return c.restConfig, err
} }
log.Debugf("Connecting to API Server %s", c.restConfig.Host) log.Debug().Msgf("Connecting to API Server %s", c.restConfig.Host)
} }
return c.restConfig, nil return c.restConfig, nil
} }

View File

@ -6,10 +6,15 @@ import (
"testing" "testing"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
"github.com/rs/zerolog"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
) )
func init() {
zerolog.SetGlobalLevel(zerolog.FatalLevel)
}
func TestConfigCurrentContext(t *testing.T) { func TestConfigCurrentContext(t *testing.T) {
name, kubeConfig := "blee", "./assets/config" name, kubeConfig := "blee", "./assets/config"
uu := []struct { uu := []struct {
@ -78,7 +83,6 @@ func TestConfigCurrentNamespace(t *testing.T) {
for _, u := range uu { for _, u := range uu {
cfg := k8s.NewConfig(u.flags) cfg := k8s.NewConfig(u.flags)
ns, err := cfg.CurrentNamespaceName() ns, err := cfg.CurrentNamespaceName()
fmt.Println("CRap", ns, err)
assert.Equal(t, u.err, err) assert.Equal(t, u.err, err)
assert.Equal(t, u.namespace, ns) assert.Equal(t, u.namespace, ns)
} }

View File

@ -38,5 +38,5 @@ func (*HPA) List(ns string) (Collection, error) {
// Delete a service // Delete a service
func (*HPA) Delete(ns, n string) error { func (*HPA) Delete(ns, n string) error {
opts := metav1.DeleteOptions{} opts := metav1.DeleteOptions{}
return conn.dialOrDie().Autoscaling().HorizontalPodAutoscalers(ns).Delete(n, &opts) return conn.dialOrDie().AutoscalingV2beta2().HorizontalPodAutoscalers(ns).Delete(n, &opts)
} }

View File

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"strings" "strings"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
@ -53,7 +53,7 @@ func (j *Job) Containers(ns, n string, includeInit bool) ([]string, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
log.Debug("Containers found assoc pod", pod) log.Debug().Msgf("Containers found assoc pod %v", pod)
return NewPod().(Loggable).Containers(ns, pod, includeInit) return NewPod().(Loggable).Containers(ns, pod, includeInit)
} }
@ -63,7 +63,6 @@ func (j *Job) Logs(ns, n, co string, lines int64, prev bool) *restclient.Request
if err != nil { if err != nil {
return nil return nil
} }
log.Println("Logs found assoc pod", pod)
return NewPod().(Loggable).Logs(ns, pod, co, lines, prev) return NewPod().(Loggable).Logs(ns, pod, co, lines, prev)
} }

View File

@ -3,7 +3,7 @@ package k8s
import ( import (
"fmt" "fmt"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
@ -73,7 +73,7 @@ func (r *Resource) getClient() *rest.RESTClient {
crConfig.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: codecs} crConfig.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: codecs}
crRestClient, err := rest.RESTClientFor(&crConfig) crRestClient, err := rest.RESTClientFor(&crConfig)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal().Err(err)
} }
return crRestClient return crRestClient
} }

View File

@ -5,7 +5,7 @@ import (
"path" "path"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/cli-runtime/pkg/genericclioptions/printers" "k8s.io/cli-runtime/pkg/genericclioptions/printers"
@ -103,7 +103,7 @@ func (*Base) marshalObject(o runtime.Object) (string, error) {
) )
err := p.PrintObj(o, &buff) err := p.PrintObj(o, &buff)
if err != nil { if err != nil {
log.Errorf("Marshal Error %v", err) log.Error().Msgf("Marshal Error %v", err)
return "", err return "", err
} }
return buff.String(), nil return buff.String(), nil

View File

@ -2,7 +2,7 @@ package resource
import ( import (
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
) )
// SwitchableRes represents a resource that can be switched. // SwitchableRes represents a resource that can be switched.
@ -52,7 +52,7 @@ func (r *Context) NewInstance(i interface{}) Columnar {
ii := i.(k8s.NamedContext) ii := i.(k8s.NamedContext)
c.instance = &ii c.instance = &ii
default: default:
log.Fatalf("unknown context type %#v", i) log.Fatal().Msgf("unknown context type %#v", i)
} }
c.path = c.instance.Name c.path = c.instance.Name
return c return c

View File

@ -2,7 +2,7 @@ package resource
import ( import (
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/rbac/v1" v1 "k8s.io/api/rbac/v1"
) )
@ -48,7 +48,7 @@ func (r *ClusterRole) NewInstance(i interface{}) Columnar {
ii := i.(v1.ClusterRole) ii := i.(v1.ClusterRole)
c.instance = &ii c.instance = &ii
default: default:
log.Fatalf("unknown context type %#v", i) log.Fatal().Msgf("unknown context type %#v", i)
} }
c.path = c.instance.Name c.path = c.instance.Name
return c return c

View File

@ -2,7 +2,7 @@ package resource
import ( import (
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/rbac/v1" v1 "k8s.io/api/rbac/v1"
) )
@ -48,7 +48,7 @@ func (r *ClusterRoleBinding) NewInstance(i interface{}) Columnar {
ii := i.(v1.ClusterRoleBinding) ii := i.(v1.ClusterRoleBinding)
c.instance = &ii c.instance = &ii
default: default:
log.Fatalf("unknown context type %#v", i) log.Fatal().Msgf("unknown context type %#v", i)
} }
c.path = c.instance.Name c.path = c.instance.Name
return c return c

View File

@ -4,7 +4,7 @@ import (
"time" "time"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
yaml "gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@ -52,7 +52,7 @@ func (r *CRD) NewInstance(i interface{}) Columnar {
ii := i.(unstructured.Unstructured) ii := i.(unstructured.Unstructured)
c.instance = &ii c.instance = &ii
default: default:
log.Fatalf("unknown context type %#v", i) log.Fatal().Msgf("unknown context type %#v", i)
} }
meta := c.instance.Object["metadata"].(map[string]interface{}) meta := c.instance.Object["metadata"].(map[string]interface{})
c.path = meta["name"].(string) c.path = meta["name"].(string)
@ -90,7 +90,7 @@ func (r *CRD) Fields(ns string) Row {
meta := i.Object["metadata"].(map[string]interface{}) meta := i.Object["metadata"].(map[string]interface{})
t, err := time.Parse(time.RFC3339, meta["creationTimestamp"].(string)) t, err := time.Parse(time.RFC3339, meta["creationTimestamp"].(string))
if err != nil { if err != nil {
log.Error("Fields timestamp", err) log.Error().Msgf("Fields timestamp %v", err)
} }
return append(ff, meta["name"].(string), toAge(metav1.Time{t})) return append(ff, meta["name"].(string), toAge(metav1.Time{t}))
} }

View File

@ -5,7 +5,7 @@ import (
"strconv" "strconv"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
batchv1beta1 "k8s.io/api/batch/v1beta1" batchv1beta1 "k8s.io/api/batch/v1beta1"
) )
@ -63,7 +63,7 @@ func (*CronJob) NewInstance(i interface{}) Columnar {
ii := i.(batchv1beta1.CronJob) ii := i.(batchv1beta1.CronJob)
job.instance = &ii job.instance = &ii
default: default:
log.Fatalf("Unknown %#v", i) log.Fatal().Msgf("Unknown %#v", i)
} }
job.path = job.namespacedName(job.instance.ObjectMeta) job.path = job.namespacedName(job.instance.ObjectMeta)
return job return job

View File

@ -8,7 +8,7 @@ import (
"strings" "strings"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
yaml "gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
) )
@ -60,12 +60,12 @@ func (*Custom) NewInstance(i interface{}) Columnar {
t := i.(metav1beta1.TableRow) t := i.(metav1beta1.TableRow)
cr.instance = &t cr.instance = &t
default: default:
log.Fatalf("Unknown %#v", i) log.Fatal().Msgf("Unknown %#v", i)
} }
var obj map[string]interface{} var obj map[string]interface{}
err := json.Unmarshal(cr.instance.Object.Raw, &obj) err := json.Unmarshal(cr.instance.Object.Raw, &obj)
if err != nil { if err != nil {
log.Error(err) log.Error().Err(err)
} }
meta := obj["metadata"].(map[string]interface{}) meta := obj["metadata"].(map[string]interface{})
ns := "" ns := ""
@ -137,7 +137,7 @@ func (r *Custom) Fields(ns string) Row {
var obj map[string]interface{} var obj map[string]interface{}
err := json.Unmarshal(r.instance.Object.Raw, &obj) err := json.Unmarshal(r.instance.Object.Raw, &obj)
if err != nil { if err != nil {
log.Error(err) log.Error().Err(err)
return Row{} return Row{}
} }

View File

@ -4,7 +4,7 @@ import (
"strconv" "strconv"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/apps/v1" v1 "k8s.io/api/apps/v1"
) )
@ -50,7 +50,7 @@ func (*Deployment) NewInstance(i interface{}) Columnar {
ii := i.(v1.Deployment) ii := i.(v1.Deployment)
cm.instance = &ii cm.instance = &ii
default: default:
log.Fatalf("Unknown %#v", i) log.Fatal().Msgf("Unknown %#v", i)
} }
cm.path = cm.namespacedName(cm.instance.ObjectMeta) cm.path = cm.namespacedName(cm.instance.ObjectMeta)
return cm return cm

View File

@ -4,7 +4,7 @@ import (
"strconv" "strconv"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
extv1beta1 "k8s.io/api/extensions/v1beta1" extv1beta1 "k8s.io/api/extensions/v1beta1"
) )
@ -50,7 +50,7 @@ func (*DaemonSet) NewInstance(i interface{}) Columnar {
ii := i.(extv1beta1.DaemonSet) ii := i.(extv1beta1.DaemonSet)
cm.instance = &ii cm.instance = &ii
default: default:
log.Fatalf("Unknown %#v", i) log.Fatal().Msgf("Unknown %#v", i)
} }
cm.path = cm.namespacedName(cm.instance.ObjectMeta) cm.path = cm.namespacedName(cm.instance.ObjectMeta)
return cm return cm

View File

@ -6,7 +6,7 @@ import (
"strings" "strings"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
) )
@ -52,7 +52,7 @@ func (*Endpoints) NewInstance(i interface{}) Columnar {
ii := i.(v1.Endpoints) ii := i.(v1.Endpoints)
cm.instance = &ii cm.instance = &ii
default: default:
log.Fatalf("Unknown %#v", i) log.Fatal().Msgf("Unknown %#v", i)
} }
cm.path = cm.namespacedName(cm.instance.ObjectMeta) cm.path = cm.namespacedName(cm.instance.ObjectMeta)
return cm return cm

View File

@ -5,7 +5,7 @@ import (
"strconv" "strconv"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
) )
@ -51,7 +51,7 @@ func (*Event) NewInstance(i interface{}) Columnar {
ii := i.(v1.Event) ii := i.(v1.Event)
cm.instance = &ii cm.instance = &ii
default: default:
log.Fatalf("Unknown %#v", i) log.Fatal().Msgf("Unknown %#v", i)
} }
cm.path = cm.namespacedName(cm.instance.ObjectMeta) cm.path = cm.namespacedName(cm.instance.ObjectMeta)
return cm return cm

View File

@ -6,8 +6,7 @@ import (
"strings" "strings"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/autoscaling/v1"
autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2" autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
) )
@ -53,7 +52,7 @@ func (*HPA) NewInstance(i interface{}) Columnar {
ii := i.(autoscalingv2beta2.HorizontalPodAutoscaler) ii := i.(autoscalingv2beta2.HorizontalPodAutoscaler)
cm.instance = &ii cm.instance = &ii
default: default:
log.Fatalf("Unknown %#v", i) log.Fatal().Msgf("Unknown %#v", i)
} }
cm.path = cm.namespacedName(cm.instance.ObjectMeta) cm.path = cm.namespacedName(cm.instance.ObjectMeta)
return cm return cm
@ -67,8 +66,8 @@ func (r *HPA) Marshal(path string) (string, error) {
return "", err return "", err
} }
hpa := i.(*v1.HorizontalPodAutoscaler) hpa := i.(*autoscalingv2beta2.HorizontalPodAutoscaler)
hpa.TypeMeta.APIVersion = "autoscaling/v1" hpa.TypeMeta.APIVersion = "autoscaling/v2beta2"
hpa.TypeMeta.Kind = "HorizontalPodAutoscaler" hpa.TypeMeta.Kind = "HorizontalPodAutoscaler"
return r.marshalObject(hpa) return r.marshalObject(hpa)
} }

View File

@ -5,9 +5,12 @@ import (
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
"github.com/derailed/k9s/internal/resource" "github.com/derailed/k9s/internal/resource"
res "k8s.io/apimachinery/pkg/api/resource"
m "github.com/petergtz/pegomock" m "github.com/petergtz/pegomock"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
v1 "k8s.io/api/autoscaling/v1" autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
@ -86,26 +89,46 @@ func TestHPAListDescribe(t *testing.T) {
// Helpers... // Helpers...
func k8sHPA() *v1.HorizontalPodAutoscaler { func k8sHPA() *autoscalingv2beta2.HorizontalPodAutoscaler {
var i int32 = 1 var i int32 = 1
return &v1.HorizontalPodAutoscaler{ return &autoscalingv2beta2.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Namespace: "blee", Namespace: "blee",
Name: "fred", Name: "fred",
CreationTimestamp: metav1.Time{Time: testTime()}, CreationTimestamp: metav1.Time{Time: testTime()},
}, },
Spec: v1.HorizontalPodAutoscalerSpec{ Spec: autoscalingv2beta2.HorizontalPodAutoscalerSpec{
ScaleTargetRef: v1.CrossVersionObjectReference{ ScaleTargetRef: autoscalingv2beta2.CrossVersionObjectReference{
Kind: "fred", Kind: "fred",
Name: "blee", Name: "blee",
}, },
MinReplicas: &i, MinReplicas: &i,
MaxReplicas: 1, MaxReplicas: 1,
TargetCPUUtilizationPercentage: &i, Metrics: []autoscalingv2beta2.MetricSpec{
{
Type: autoscalingv2beta2.ResourceMetricSourceType,
Resource: &autoscalingv2beta2.ResourceMetricSource{
Name: v1.ResourceCPU,
Target: autoscalingv2beta2.MetricTarget{
Type: autoscalingv2beta2.UtilizationMetricType,
},
},
},
},
}, },
Status: v1.HorizontalPodAutoscalerStatus{ Status: autoscalingv2beta2.HorizontalPodAutoscalerStatus{
CurrentReplicas: 1, CurrentReplicas: 1,
CurrentCPUUtilizationPercentage: &i, CurrentMetrics: []autoscalingv2beta2.MetricStatus{
{
Type: autoscalingv2beta2.ResourceMetricSourceType,
Resource: &autoscalingv2beta2.ResourceMetricStatus{
Name: v1.ResourceCPU,
Current: autoscalingv2beta2.MetricValueStatus{
Value: &res.Quantity{},
},
},
},
},
}, },
} }
} }
@ -115,7 +138,7 @@ func newHPA() resource.Columnar {
} }
func hpaYaml() string { func hpaYaml() string {
return `apiVersion: autoscaling/v1 return `apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler kind: HorizontalPodAutoscaler
metadata: metadata:
creationTimestamp: "2018-12-14T17:36:43Z" creationTimestamp: "2018-12-14T17:36:43Z"
@ -123,13 +146,24 @@ metadata:
namespace: blee namespace: blee
spec: spec:
maxReplicas: 1 maxReplicas: 1
metrics:
- resource:
name: cpu
target:
type: Utilization
type: Resource
minReplicas: 1 minReplicas: 1
scaleTargetRef: scaleTargetRef:
kind: fred kind: fred
name: blee name: blee
targetCPUUtilizationPercentage: 1
status: status:
currentCPUUtilizationPercentage: 1 conditions: null
currentMetrics:
- resource:
current:
value: "0"
name: cpu
type: Resource
currentReplicas: 1 currentReplicas: 1
desiredReplicas: 0 desiredReplicas: 0
` `

View File

@ -4,7 +4,7 @@ import (
"strings" "strings"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
"k8s.io/api/extensions/v1beta1" "k8s.io/api/extensions/v1beta1"
) )
@ -51,7 +51,7 @@ func (*Ingress) NewInstance(i interface{}) Columnar {
ii := i.(v1beta1.Ingress) ii := i.(v1beta1.Ingress)
cm.instance = &ii cm.instance = &ii
default: default:
log.Fatalf("Unknown %#v", i) log.Fatal().Msgf("Unknown %#v", i)
} }
cm.path = cm.namespacedName(cm.instance.ObjectMeta) cm.path = cm.namespacedName(cm.instance.ObjectMeta)
return cm return cm

View File

@ -7,7 +7,7 @@ import (
"time" "time"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/batch/v1" v1 "k8s.io/api/batch/v1"
"k8s.io/apimachinery/pkg/util/duration" "k8s.io/apimachinery/pkg/util/duration"
) )
@ -54,7 +54,7 @@ func (*Job) NewInstance(i interface{}) Columnar {
ii := i.(v1.Job) ii := i.(v1.Job)
job.instance = &ii job.instance = &ii
default: default:
log.Fatalf("Unknown %#v", i) log.Fatal().Msgf("Unknown %#v", i)
} }
job.path = job.namespacedName(job.instance.ObjectMeta) job.path = job.namespacedName(job.instance.ObjectMeta)
return job return job

View File

@ -6,7 +6,7 @@ import (
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
) )
@ -60,7 +60,7 @@ func (*Node) NewInstance(i interface{}) Columnar {
ii := i.(v1.Node) ii := i.(v1.Node)
cm.instance = &ii cm.instance = &ii
default: default:
log.Fatalf("Unknown %#v", i) log.Fatal().Msgf("Unknown %#v", i)
} }
cm.path = cm.namespacedName(cm.instance.ObjectMeta) cm.path = cm.namespacedName(cm.instance.ObjectMeta)
return cm return cm
@ -81,7 +81,7 @@ func (r *Node) List(ns string) (Columnars, error) {
cc := make(Columnars, 0, len(nn)) cc := make(Columnars, 0, len(nn))
mx, err := r.metricSvc.PerNodeMetrics(nn) mx, err := r.metricSvc.PerNodeMetrics(nn)
if err != nil { if err != nil {
log.Warnf("No metrics: %#v", err) log.Warn().Msgf("No metrics: %#v", err)
} }
for i := 0; i < len(nn); i++ { for i := 0; i < len(nn); i++ {
@ -99,7 +99,7 @@ func (r *Node) Marshal(path string) (string, error) {
ns, n := namespaced(path) ns, n := namespaced(path)
i, err := r.caller.Get(ns, n) i, err := r.caller.Get(ns, n)
if err != nil { if err != nil {
log.Error(err) log.Error().Err(err)
return "", err return "", err
} }

View File

@ -2,7 +2,7 @@ package resource
import ( import (
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
) )
@ -48,7 +48,7 @@ func (*Namespace) NewInstance(i interface{}) Columnar {
ii := i.(v1.Namespace) ii := i.(v1.Namespace)
cm.instance = &ii cm.instance = &ii
default: default:
log.Fatalf("Unknown %#v", i) log.Fatal().Msgf("Unknown %#v", i)
} }
cm.path = cm.namespacedName(cm.instance.ObjectMeta) cm.path = cm.namespacedName(cm.instance.ObjectMeta)
return cm return cm
@ -59,7 +59,7 @@ func (r *Namespace) Marshal(path string) (string, error) {
ns, n := namespaced(path) ns, n := namespaced(path)
i, err := r.caller.Get(ns, n) i, err := r.caller.Get(ns, n)
if err != nil { if err != nil {
log.Error(err) log.Error().Err(err)
return "", err return "", err
} }

View File

@ -8,7 +8,7 @@ import (
"time" "time"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
) )
@ -86,7 +86,7 @@ func (r *Pod) NewInstance(i interface{}) Columnar {
po := ptr.(v1.Pod) po := ptr.(v1.Pod)
pod.instance = &po pod.instance = &po
default: default:
log.Fatalf("Unknown %#v", i) log.Fatal().Msgf("Unknown %#v", i)
} }
pod.path = r.namespacedName(pod.instance.ObjectMeta) pod.path = r.namespacedName(pod.instance.ObjectMeta)
return pod return pod
@ -169,7 +169,7 @@ func (r *Pod) List(ns string) (Columnars, error) {
metrics, err := r.metricSvc.PodMetrics() metrics, err := r.metricSvc.PodMetrics()
if err != nil { if err != nil {
log.Warn(err) log.Error().Err(err)
} }
cc := make(Columnars, 0, len(ii)) cc := make(Columnars, 0, len(ii))
@ -221,7 +221,7 @@ func (r *Pod) Fields(ns string) Row {
r.metrics.CPU, r.metrics.CPU,
r.metrics.Mem, r.metrics.Mem,
i.Status.PodIP, i.Status.PodIP,
i.Status.HostIP, i.Spec.NodeName,
string(i.Status.QOSClass), string(i.Status.QOSClass),
toAge(i.ObjectMeta.CreationTimestamp), toAge(i.ObjectMeta.CreationTimestamp),
) )
@ -231,15 +231,6 @@ func (r *Pod) Fields(ns string) Row {
func (r *Pod) ExtFields() Properties { func (r *Pod) ExtFields() Properties {
i := r.instance i := r.instance
// po := k8s.Pod{}
// e, err := po.Events(i.Namespace, i.Name)
// if err != nil {
// log.Error("Boom!", err)
// }
// if len(e.Items) > 0 {
// log.Println("Events", ee.Items)
// }
return Properties{ return Properties{
"Priority": strconv.Itoa(int(*i.Spec.Priority)), "Priority": strconv.Itoa(int(*i.Spec.Priority)),
"Priority Class": missing(i.Spec.PriorityClassName), "Priority Class": missing(i.Spec.PriorityClassName),
@ -249,22 +240,9 @@ func (r *Pod) ExtFields() Properties {
"Init Containers": r.toContainers(i.Spec.InitContainers), "Init Containers": r.toContainers(i.Spec.InitContainers),
"Node Selectors": mapToStr(i.Spec.NodeSelector), "Node Selectors": mapToStr(i.Spec.NodeSelector),
"Volumes": r.toVolumes(i.Spec.Volumes), "Volumes": r.toVolumes(i.Spec.Volumes),
// "Events": r.toEvents(e),
} }
} }
// func (r *Pod) toEvents(e *v1.EventList) []string {
// ss := make([]string, 0, len(e.Items)+1)
// for _, h := range([]string{"Type", "Reason", "From", "Message", "Age"}) {
// ss[0] = fmt.Printf("%10s %10s %20s %30s", )
// }
// for i, e := range e.Items {
// ss[i] = e.
// }
// return ss
// }
func (r *Pod) toVolumes(vv []v1.Volume) map[string]interface{} { func (r *Pod) toVolumes(vv []v1.Volume) map[string]interface{} {
m := make(map[string]interface{}, len(vv)) m := make(map[string]interface{}, len(vv))
for _, v := range vv { for _, v := range vv {

View File

@ -5,7 +5,7 @@ import (
"strings" "strings"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
) )
@ -51,7 +51,7 @@ func (*PV) NewInstance(i interface{}) Columnar {
ii := i.(v1.PersistentVolume) ii := i.(v1.PersistentVolume)
cm.instance = &ii cm.instance = &ii
default: default:
log.Fatalf("Unknown %#v", i) log.Fatal().Msgf("Unknown %#v", i)
} }
cm.path = cm.namespacedName(cm.instance.ObjectMeta) cm.path = cm.namespacedName(cm.instance.ObjectMeta)
return cm return cm

View File

@ -2,7 +2,7 @@ package resource
import ( import (
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
) )
@ -48,7 +48,7 @@ func (*PVC) NewInstance(i interface{}) Columnar {
ii := i.(v1.PersistentVolumeClaim) ii := i.(v1.PersistentVolumeClaim)
cm.instance = &ii cm.instance = &ii
default: default:
log.Fatalf("Unknown %#v", i) log.Fatal().Msgf("Unknown %#v", i)
} }
cm.path = cm.namespacedName(cm.instance.ObjectMeta) cm.path = cm.namespacedName(cm.instance.ObjectMeta)
return cm return cm

View File

@ -4,7 +4,7 @@ import (
"strconv" "strconv"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
) )
@ -50,7 +50,7 @@ func (*ReplicationController) NewInstance(i interface{}) Columnar {
ii := i.(v1.ReplicationController) ii := i.(v1.ReplicationController)
cm.instance = &ii cm.instance = &ii
default: default:
log.Fatalf("Unknown %#v", i) log.Fatal().Msgf("Unknown %#v", i)
} }
cm.path = cm.namespacedName(cm.instance.ObjectMeta) cm.path = cm.namespacedName(cm.instance.ObjectMeta)
return cm return cm

View File

@ -4,7 +4,7 @@ import (
"strings" "strings"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/rbac/v1" v1 "k8s.io/api/rbac/v1"
) )
@ -52,7 +52,7 @@ func (*Role) NewInstance(i interface{}) Columnar {
ii := i.(v1.Role) ii := i.(v1.Role)
cm.instance = &ii cm.instance = &ii
default: default:
log.Fatalf("Unknown %#v", i) log.Fatal().Msgf("Unknown %#v", i)
} }
cm.path = cm.namespacedName(cm.instance.ObjectMeta) cm.path = cm.namespacedName(cm.instance.ObjectMeta)
return cm return cm

View File

@ -4,7 +4,7 @@ import (
"strings" "strings"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/rbac/v1" v1 "k8s.io/api/rbac/v1"
) )
@ -50,7 +50,7 @@ func (*RoleBinding) NewInstance(i interface{}) Columnar {
ii := i.(v1.RoleBinding) ii := i.(v1.RoleBinding)
cm.instance = &ii cm.instance = &ii
default: default:
log.Fatalf("Unknown %#v", i) log.Fatal().Msgf("Unknown %#v", i)
} }
cm.path = cm.namespacedName(cm.instance.ObjectMeta) cm.path = cm.namespacedName(cm.instance.ObjectMeta)
return cm return cm

View File

@ -4,7 +4,7 @@ import (
"strconv" "strconv"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/apps/v1" v1 "k8s.io/api/apps/v1"
) )
@ -50,7 +50,7 @@ func (*ReplicaSet) NewInstance(i interface{}) Columnar {
ii := i.(v1.ReplicaSet) ii := i.(v1.ReplicaSet)
cm.instance = &ii cm.instance = &ii
default: default:
log.Fatalf("Unknown %#v", i) log.Fatal().Msgf("Unknown %#v", i)
} }
cm.path = cm.namespacedName(cm.instance.ObjectMeta) cm.path = cm.namespacedName(cm.instance.ObjectMeta)
return cm return cm

View File

@ -4,7 +4,7 @@ import (
"strconv" "strconv"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
) )
@ -50,7 +50,7 @@ func (*ServiceAccount) NewInstance(i interface{}) Columnar {
ii := i.(v1.ServiceAccount) ii := i.(v1.ServiceAccount)
cm.instance = &ii cm.instance = &ii
default: default:
log.Fatalf("Unknown %#v", i) log.Fatal().Msgf("Unknown %#v", i)
} }
cm.path = cm.namespacedName(cm.instance.ObjectMeta) cm.path = cm.namespacedName(cm.instance.ObjectMeta)
return cm return cm

View File

@ -4,7 +4,7 @@ import (
"strconv" "strconv"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/apps/v1" v1 "k8s.io/api/apps/v1"
) )
@ -50,7 +50,7 @@ func (*StatefulSet) NewInstance(i interface{}) Columnar {
ii := i.(v1.StatefulSet) ii := i.(v1.StatefulSet)
cm.instance = &ii cm.instance = &ii
default: default:
log.Fatalf("Unknown %#v", i) log.Fatal().Msgf("Unknown %#v", i)
} }
cm.path = cm.namespacedName(cm.instance.ObjectMeta) cm.path = cm.namespacedName(cm.instance.ObjectMeta)
return cm return cm

View File

@ -6,7 +6,7 @@ import (
"strings" "strings"
"github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
) )
@ -54,7 +54,7 @@ func (*Service) NewInstance(i interface{}) Columnar {
ii := i.(v1.Service) ii := i.(v1.Service)
cm.instance = &ii cm.instance = &ii
default: default:
log.Fatalf("Unknown %#v", i) log.Fatal().Msgf("Unknown %#v", i)
} }
cm.path = cm.namespacedName(cm.instance.ObjectMeta) cm.path = cm.namespacedName(cm.instance.ObjectMeta)
return cm return cm

View File

@ -9,7 +9,7 @@ import (
"github.com/derailed/k9s/internal/resource" "github.com/derailed/k9s/internal/resource"
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
) )
const ( const (
@ -42,7 +42,7 @@ func newAliasView(app *appView) *aliasView {
for { for {
select { select {
case <-ctx.Done(): case <-ctx.Done():
log.Debug("Alias GR bailing out!") log.Debug().Msg("Alias GR bailing out!")
return return
case <-time.After(1 * time.Second): case <-time.After(1 * time.Second):
v.update(v.hydrate()) v.update(v.hydrate())

View File

@ -8,7 +8,7 @@ import (
"github.com/derailed/k9s/internal/config" "github.com/derailed/k9s/internal/config"
"github.com/derailed/tview" "github.com/derailed/tview"
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
) )
@ -136,7 +136,7 @@ func (a *appView) keyboard(evt *tcell.EventKey) *tcell.EventKey {
key = tcell.Key(evt.Rune()) key = tcell.Key(evt.Rune())
} }
if a, ok := a.actions[key]; ok { if a, ok := a.actions[key]; ok {
log.Debug(">> AppView handled key: ", tcell.KeyNames[key]) log.Debug().Msgf(">> AppView handled key: %s", tcell.KeyNames[key])
return a.action(evt) return a.action(evt)
} }
return evt return evt
@ -178,8 +178,11 @@ func (a *appView) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
} }
func (a *appView) activateCmd(evt *tcell.EventKey) *tcell.EventKey { func (a *appView) activateCmd(evt *tcell.EventKey) *tcell.EventKey {
if a.cmdView.inCmdMode() {
return evt
}
a.flash(flashInfo, "Entering command mode...") a.flash(flashInfo, "Entering command mode...")
log.Debug("Entering app command mode...") log.Debug().Msg("Entering app command mode...")
a.cmdBuff.setActive(true) a.cmdBuff.setActive(true)
a.cmdBuff.clear() a.cmdBuff.clear()
return nil return nil

View File

@ -5,7 +5,7 @@ import (
"github.com/derailed/tview" "github.com/derailed/tview"
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
) )
const defaultPrompt = "%c> %s" const defaultPrompt = "%c> %s"
@ -62,7 +62,7 @@ func (v *cmdView) changed(s string) {
func (v *cmdView) active(f bool) { func (v *cmdView) active(f bool) {
v.activated = f v.activated = f
if f { if f {
log.Debug("CmdView was activated...") log.Debug().Msg("CmdView was activated...")
v.SetBackgroundColor(tcell.ColorDodgerBlue) v.SetBackgroundColor(tcell.ColorDodgerBlue)
v.activate() v.activate()
} else { } else {

View File

@ -8,7 +8,7 @@ import (
"github.com/derailed/tview" "github.com/derailed/tview"
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
) )
const detailsTitleFmt = " [aqua::b]%s([fuchsia::b]%s[aqua::-])[aqua::-] " const detailsTitleFmt = " [aqua::b]%s([fuchsia::b]%s[aqua::-])[aqua::-] "
@ -26,6 +26,11 @@ type detailsView struct {
numSelections int numSelections int
} }
var (
regionRX = regexp.MustCompile(`\["([a-zA-Z0-9_,;: \-\.]*)"\]`)
escapeRX = regexp.MustCompile(`\[([a-zA-Z0-9_,;: \-\."#]+)\[(\[*)\]`)
)
func newDetailsView(app *appView, backFn actionHandler) *detailsView { func newDetailsView(app *appView, backFn actionHandler) *detailsView {
v := detailsView{TextView: tview.NewTextView(), app: app, actions: make(keyActions)} v := detailsView{TextView: tview.NewTextView(), app: app, actions: make(keyActions)}
{ {
@ -74,7 +79,7 @@ func (v *detailsView) keyboard(evt *tcell.EventKey) *tcell.EventKey {
} }
if a, ok := v.actions[key]; ok { if a, ok := v.actions[key]; ok {
log.Debug(">> DetailsView handled ", tcell.KeyNames[key]) log.Debug().Msgf(">> DetailsView handled %s", tcell.KeyNames[key])
return a.action(evt) return a.action(evt)
} }
return evt return evt
@ -128,8 +133,9 @@ func (v *detailsView) searchCmd(evt *tcell.EventKey) *tcell.EventKey {
func (v *detailsView) search(evt *tcell.EventKey) { func (v *detailsView) search(evt *tcell.EventKey) {
v.numSelections = 0 v.numSelections = 0
v.Highlight() v.Highlight()
log.Debug("Searching...", v.cmdBuff, v.numSelections) log.Debug().Msgf("Searching... %s - %d", v.cmdBuff, v.numSelections)
v.SetText(v.decorateLines(v.GetText(true), v.cmdBuff.String())) v.Highlight("")
v.SetText(v.decorateLines(v.GetText(false), v.cmdBuff.String()))
if v.cmdBuff.empty() { if v.cmdBuff.empty() {
v.app.flash(flashWarn, "Clearing out search query...") v.app.flash(flashWarn, "Clearing out search query...")
@ -203,9 +209,13 @@ func (v *detailsView) decorateLines(buff, q string) string {
rx := regexp.MustCompile(`(?i)` + q) rx := regexp.MustCompile(`(?i)` + q)
lines := strings.Split(buff, "\n") lines := strings.Split(buff, "\n")
for i, l := range lines { for i, l := range lines {
l = regionRX.ReplaceAllString(l, "")
l = escapeRX.ReplaceAllString(l, "")
if m := rx.FindString(l); len(m) > 0 { if m := rx.FindString(l); len(m) > 0 {
lines[i] = rx.ReplaceAllString(l, fmt.Sprintf(`["%d"]%s[""]`, v.numSelections, m)) lines[i] = rx.ReplaceAllString(l, fmt.Sprintf(`["%d"]%s[""]`, v.numSelections, m))
v.numSelections++ v.numSelections++
} else {
lines[i] = l
} }
} }
return strings.Join(lines, "\n") return strings.Join(lines, "\n")

View File

@ -10,13 +10,13 @@ import (
"strings" "strings"
"syscall" "syscall"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
) )
func runK(app *appView, args ...string) bool { func runK(app *appView, args ...string) bool {
bin, err := exec.LookPath("kubectl") bin, err := exec.LookPath("kubectl")
if err != nil { if err != nil {
log.Error("Unable to find kubeclt command in path") log.Error().Msgf("Unable to find kubeclt command in path %v", err)
return false return false
} }
@ -31,7 +31,7 @@ func runK(app *appView, args ...string) bool {
} }
} }
if err := execute(bin, args...); err != nil { if err := execute(bin, args...); err != nil {
log.Errorf("Command exited: %T %v %v", err, err, args) log.Error().Msgf("Command exited: %T %v %v", err, err, args)
app.flash(flashErr, "Command exited:", err.Error()) app.flash(flashErr, "Command exited:", err.Error())
} }
}) })
@ -40,7 +40,7 @@ func runK(app *appView, args ...string) bool {
func run1(app *appView, bin string, args ...string) bool { func run1(app *appView, bin string, args ...string) bool {
return app.Suspend(func() { return app.Suspend(func() {
if err := execute(bin, args...); err != nil { if err := execute(bin, args...); err != nil {
log.Errorf("Command exited: %T %v %v", err, err, args) log.Error().Msgf("Command exited: %T %v %v", err, err, args)
app.flash(flashErr, "Command exited: ", err.Error()) app.flash(flashErr, "Command exited: ", err.Error())
} }
}) })
@ -48,7 +48,7 @@ func run1(app *appView, bin string, args ...string) bool {
func execute(bin string, args ...string) error { func execute(bin string, args ...string) error {
clearScreen() clearScreen()
log.Debugf("Running command > %s %s", bin, strings.Join(args, " ")) log.Debug().Msgf("Running command > %s %s", bin, strings.Join(args, " "))
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
@ -56,14 +56,14 @@ func execute(bin string, args ...string) error {
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM) signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
go func() { go func() {
<-sigChan <-sigChan
log.Debug("Command canceled with signal!") log.Debug().Msg("Command canceled with signal!")
cancel() cancel()
}() }()
cmd := exec.Command(bin, args...) cmd := exec.Command(bin, args...)
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
err := cmd.Run() err := cmd.Run()
log.Debug("Command return status ", err) log.Debug().Msgf("Command return status %v", err)
select { select {
case <-ctx.Done(): case <-ctx.Done():
return errors.New("canceled by operator") return errors.New("canceled by operator")

View File

@ -14,7 +14,7 @@ const (
flashWarn flashWarn
flashErr flashErr
flashFatal flashFatal
flashDelay = 5 flashDelay = 3
emoDoh = "😗" emoDoh = "😗"
emoRed = "😡" emoRed = "😡"

View File

@ -4,7 +4,7 @@ import (
"github.com/derailed/k9s/internal/resource" "github.com/derailed/k9s/internal/resource"
"github.com/derailed/tview" "github.com/derailed/tview"
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
) )
type infoView struct { type infoView struct {
@ -77,7 +77,7 @@ func (v *infoView) refresh() {
mx, err := cluster.Metrics() mx, err := cluster.Metrics()
if err != nil { if err != nil {
log.Error(err) log.Error().Err(err)
return return
} }
c := v.GetCell(row, 1) c := v.GetCell(row, 1)

View File

@ -3,7 +3,7 @@ package views
import ( import (
"github.com/derailed/k9s/internal/resource" "github.com/derailed/k9s/internal/resource"
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
) )
type jobView struct { type jobView struct {
@ -48,7 +48,7 @@ func (v *jobView) logs(evt *tcell.EventKey) *tcell.EventKey {
cc, err := fetchContainers(v.list, v.selectedItem, true) cc, err := fetchContainers(v.list, v.selectedItem, true)
if err != nil { if err != nil {
v.app.flash(flashErr, err.Error()) v.app.flash(flashErr, err.Error())
log.Error(err) log.Error().Err(err)
return evt return evt
} }

View File

@ -2,10 +2,14 @@ package views
import ( import (
"fmt" "fmt"
"io"
"github.com/derailed/tview"
) )
type logView struct { type logView struct {
*detailsView *detailsView
ansiWriter io.Writer
} }
func newLogView(title string, parent loggable) *logView { func newLogView(title string, parent loggable) *logView {
@ -13,14 +17,19 @@ func newLogView(title string, parent loggable) *logView {
{ {
v.SetBorderPadding(0, 0, 1, 1) v.SetBorderPadding(0, 0, 1, 1)
v.setCategory("Logs") v.setCategory("Logs")
v.SetDynamicColors(false) v.SetDynamicColors(true)
v.SetWrap(true) v.SetWrap(true)
v.setTitle(parent.getSelection()) v.setTitle(parent.getSelection())
} }
v.ansiWriter = tview.ANSIWriter(v)
return &v return &v
} }
func (l *logView) logLine(line string) {
fmt.Fprintln(l.ansiWriter, line)
}
func (l *logView) log(lines fmt.Stringer) { func (l *logView) log(lines fmt.Stringer) {
l.Clear() l.Clear()
fmt.Fprintln(l, lines.String()) fmt.Fprintln(l.ansiWriter, lines.String())
} }

View File

@ -10,7 +10,7 @@ import (
"github.com/derailed/k9s/internal/resource" "github.com/derailed/k9s/internal/resource"
"github.com/derailed/tview" "github.com/derailed/tview"
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
) )
const ( const (
@ -26,16 +26,13 @@ type logsView struct {
containers []string containers []string
actions keyActions actions keyActions
cancelFunc context.CancelFunc cancelFunc context.CancelFunc
buffer *logBuffer
} }
func newLogsView(parent loggable) *logsView { func newLogsView(parent loggable) *logsView {
maxBuff := config.Root.K9s.LogBufferSize
v := logsView{ v := logsView{
Pages: tview.NewPages(), Pages: tview.NewPages(),
parent: parent, parent: parent,
containers: []string{}, containers: []string{},
buffer: newLogBuffer(int(maxBuff), true),
} }
v.setActions(keyActions{ v.setActions(keyActions{
tcell.KeyEscape: {description: "Back", action: v.back}, tcell.KeyEscape: {description: "Back", action: v.back},
@ -57,27 +54,31 @@ func (v *logsView) init() {
} }
func (v *logsView) keyboard(evt *tcell.EventKey) *tcell.EventKey { func (v *logsView) keyboard(evt *tcell.EventKey) *tcell.EventKey {
key := evt.Key()
if key == tcell.KeyRune {
key = tcell.Key(evt.Rune())
}
if kv, ok := v.CurrentPage().Item.(keyHandler); ok { if kv, ok := v.CurrentPage().Item.(keyHandler); ok {
if kv.keyboard(evt) == nil { if kv.keyboard(evt) == nil {
return nil return nil
} }
} }
key := evt.Key() if evt.Key() == tcell.KeyRune {
if key == tcell.KeyRune {
if i, err := strconv.Atoi(string(evt.Rune())); err == nil { if i, err := strconv.Atoi(string(evt.Rune())); err == nil {
if _, ok := numKeys[i]; ok { if _, ok := numKeys[i]; ok {
v.load(i - 1) v.load(i - 1)
return nil return nil
} }
} }
key = tcell.Key(evt.Rune())
} }
if m, ok := v.actions[key]; ok { if m, ok := v.actions[key]; ok {
log.Debug(">> LogsView handled ", tcell.KeyNames[key]) log.Debug().Msgf(">> LogsView handled %s", tcell.KeyNames[key])
return m.action(evt) return m.action(evt)
} }
return evt return evt
} }
@ -101,6 +102,7 @@ func (v *logsView) addContainer(n string) {
l := newLogView(n, v.parent) l := newLogView(n, v.parent)
{ {
l.SetInputCapture(v.keyboard) l.SetInputCapture(v.keyboard)
l.backFn = v.back
} }
v.AddPage(n, l, true, false) v.AddPage(n, l, true, false)
} }
@ -114,7 +116,12 @@ func (v *logsView) deleteAllPages() {
} }
func (v *logsView) stop() { func (v *logsView) stop() {
v.killLogIfAny() if v.cancelFunc == nil {
return
}
log.Debug().Msg("Canceling logs...")
v.cancelFunc()
v.cancelFunc = nil
} }
func (v *logsView) load(i int) { func (v *logsView) load(i int) {
@ -122,60 +129,31 @@ func (v *logsView) load(i int) {
return return
} }
v.SwitchToPage(v.containers[i]) v.SwitchToPage(v.containers[i])
v.buffer.clear()
if err := v.doLoad(v.parent.getSelection(), v.containers[i]); err != nil { if err := v.doLoad(v.parent.getSelection(), v.containers[i]); err != nil {
v.parent.appView().flash(flashErr, err.Error()) v.parent.appView().flash(flashErr, err.Error())
v.buffer.add("😂 Doh! No logs are available at this time. Check again later on...")
l := v.CurrentPage().Item.(*logView) l := v.CurrentPage().Item.(*logView)
l.log(v.buffer) l.logLine("😂 Doh! No logs are available at this time. Check again later on...")
return return
} }
v.parent.appView().SetFocus(v) v.parent.appView().SetFocus(v)
} }
func (v *logsView) killLogIfAny() {
if v.cancelFunc == nil {
return
}
v.cancelFunc()
v.cancelFunc = nil
}
func (v *logsView) doLoad(path, co string) error { func (v *logsView) doLoad(path, co string) error {
v.killLogIfAny() v.stop()
c := make(chan string) c := make(chan string)
go func() { go func() {
l, count, first := v.CurrentPage().Item.(*logView), 0, true l := v.CurrentPage().Item.(*logView)
l.setTitle(path + ":" + co) l.setTitle(path + ":" + co)
for { for {
select { select {
case line, ok := <-c: case line, ok := <-c:
if !ok { if !ok {
if v.buffer.length() > 0 { l.logLine("--- No more logs ---")
v.buffer.add("--- No more logs ---") l.ScrollToEnd()
l.log(v.buffer)
l.ScrollToEnd()
}
return return
} }
v.buffer.add(line) l.logLine(line)
case <-time.After(refreshRate):
if count == maxCleanse {
log.Debug("Cleansing logs")
v.buffer.cleanse()
count = 0
}
count++
if v.buffer.length() == 0 {
l.Clear()
continue
}
l.log(v.buffer)
if first {
l.ScrollToEnd()
first = false
}
} }
} }
}() }()
@ -185,8 +163,8 @@ func (v *logsView) doLoad(path, co string) error {
if !ok { if !ok {
return fmt.Errorf("Resource %T is not tailable", v.parent.getList().Resource) return fmt.Errorf("Resource %T is not tailable", v.parent.getList().Resource)
} }
maxBuff := config.Root.K9s.LogBufferSize maxBuff := int64(config.Root.K9s.LogBufferSize)
cancelFn, err := res.Logs(c, ns, po, co, int64(maxBuff), false) cancelFn, err := res.Logs(c, ns, po, co, maxBuff, false)
if err != nil { if err != nil {
cancelFn() cancelFn()
return err return err
@ -237,7 +215,6 @@ func (v *logsView) pageDown(*tcell.EventKey) *tcell.EventKey {
func (v *logsView) clearLogs(*tcell.EventKey) *tcell.EventKey { func (v *logsView) clearLogs(*tcell.EventKey) *tcell.EventKey {
if p := v.CurrentPage(); p != nil { if p := v.CurrentPage(); p != nil {
v.parent.appView().flash(flashInfo, "Clearing logs...") v.parent.appView().flash(flashInfo, "Clearing logs...")
v.buffer.clear()
p.Item.(*logView).Clear() p.Item.(*logView).Clear()
} }
return nil return nil

View File

@ -10,7 +10,7 @@ import (
"github.com/derailed/k9s/internal/resource" "github.com/derailed/k9s/internal/resource"
"github.com/derailed/tview" "github.com/derailed/tview"
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
) )
const ( const (
@ -143,7 +143,7 @@ func (a keyActions) toHints() hints {
mnemonic: name, mnemonic: name,
display: a[tcell.Key(k)].description}) display: a[tcell.Key(k)].description})
} else { } else {
log.Errorf("Unable to local KeyName for %#v", k) log.Error().Msgf("Unable to local KeyName for %#v", k)
} }
} }
return hh return hh

View File

@ -5,7 +5,7 @@ import (
"github.com/derailed/k9s/internal/resource" "github.com/derailed/k9s/internal/resource"
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
) )
type podView struct { type podView struct {
@ -60,14 +60,13 @@ func (v *podView) getSelection() string {
// Handlers... // Handlers...
func (v *podView) logsCmd(evt *tcell.EventKey) *tcell.EventKey { func (v *podView) logsCmd(evt *tcell.EventKey) *tcell.EventKey {
log.Println("Selected", v.rowSelected())
if !v.rowSelected() { if !v.rowSelected() {
return evt return evt
} }
cc, err := fetchContainers(v.list, v.selectedItem, true) cc, err := fetchContainers(v.list, v.selectedItem, true)
if err != nil { if err != nil {
v.app.flash(flashErr, err.Error()) v.app.flash(flashErr, err.Error())
log.Error(err) log.Error().Err(err)
return evt return evt
} }
l := v.GetPrimitive("logs").(*logsView) l := v.GetPrimitive("logs").(*logsView)
@ -117,7 +116,7 @@ func (v *podView) shellCmd(evt *tcell.EventKey) *tcell.EventKey {
cc, err := fetchContainers(v.list, v.selectedItem, false) cc, err := fetchContainers(v.list, v.selectedItem, false)
if err != nil { if err != nil {
v.app.flash(flashErr, err.Error()) v.app.flash(flashErr, err.Error())
log.Error("Error fetching containers", err) log.Error().Msgf("Error fetching containers %v", err)
return evt return evt
} }
if len(cc) == 1 { if len(cc) == 1 {
@ -146,7 +145,7 @@ func (v *podView) shellIn(path, co string) {
args = append(args, "-c", co) args = append(args, "-c", co)
} }
args = append(args, "--", "sh") args = append(args, "--", "sh")
log.Debug("Shell args", args) log.Debug().Msgf("Shell args %v", args)
runK(v.app, args...) runK(v.app, args...)
} }

View File

@ -14,7 +14,7 @@ import (
"github.com/derailed/k9s/internal/resource" "github.com/derailed/k9s/internal/resource"
"github.com/derailed/tview" "github.com/derailed/tview"
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
) )
const noSelection = "" const noSelection = ""
@ -74,7 +74,7 @@ func (v *resourceView) init(ctx context.Context, ns string) {
for { for {
select { select {
case <-ctx.Done(): case <-ctx.Done():
log.Debugf("%s watcher canceled!", v.title) log.Debug().Msgf("%s watcher canceled!", v.title)
return return
case <-time.After(time.Duration(initTick) * time.Second): case <-time.After(time.Duration(initTick) * time.Second):
v.refresh() v.refresh()
@ -118,6 +118,12 @@ func (v *resourceView) hints() hints {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Actions... // Actions...
func (v *resourceView) refreshCmd(*tcell.EventKey) *tcell.EventKey {
log.Debug().Msg("Refreshing resource...")
v.refresh()
return nil
}
func (v *resourceView) backCmd(*tcell.EventKey) *tcell.EventKey { func (v *resourceView) backCmd(*tcell.EventKey) *tcell.EventKey {
v.switchPage(v.list.GetName()) v.switchPage(v.list.GetName())
return nil return nil
@ -145,7 +151,7 @@ func (v *resourceView) describeCmd(evt *tcell.EventKey) *tcell.EventKey {
raw, err := v.list.Resource().Describe(v.title, sel) raw, err := v.list.Resource().Describe(v.title, sel)
if err != nil { if err != nil {
v.app.flash(flashErr, "Unable to describeCmd this resource", err.Error()) v.app.flash(flashErr, "Unable to describeCmd this resource", err.Error())
log.Error(err) log.Error().Err(err)
return evt return evt
} }
details := v.GetPrimitive("details").(*detailsView) details := v.GetPrimitive("details").(*detailsView)
@ -168,7 +174,7 @@ func (v *resourceView) viewCmd(evt *tcell.EventKey) *tcell.EventKey {
raw, err := v.list.Resource().Marshal(sel) raw, err := v.list.Resource().Marshal(sel)
if err != nil { if err != nil {
v.app.flash(flashErr, "Unable to marshal resource", err.Error()) v.app.flash(flashErr, "Unable to marshal resource", err.Error())
log.Error(err) log.Error().Err(err)
return evt return evt
} }
details := v.GetPrimitive("details").(*detailsView) details := v.GetPrimitive("details").(*detailsView)
@ -324,6 +330,8 @@ func (v *resourceView) refreshActions() {
} }
} }
aa[tcell.KeyCtrlR] = newKeyAction("Refresh", v.refreshCmd)
if v.list.Access(resource.EditAccess) { if v.list.Access(resource.EditAccess) {
aa[KeyE] = newKeyAction("Edit", v.editCmd) aa[KeyE] = newKeyAction("Edit", v.editCmd)
} }

View File

@ -9,7 +9,7 @@ import (
"github.com/derailed/k9s/internal/resource" "github.com/derailed/k9s/internal/resource"
"github.com/derailed/tview" "github.com/derailed/tview"
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog/log"
) )
const ( const (
@ -83,7 +83,7 @@ func (v *tableView) keyboard(evt *tcell.EventKey) *tcell.EventKey {
} }
if a, ok := v.actions[key]; ok { if a, ok := v.actions[key]; ok {
log.Debug(">> TableView handled ", tcell.KeyNames[key]) log.Debug().Msgf(">> TableView handled %s", tcell.KeyNames[key])
return a.action(evt) return a.action(evt)
} }
return evt return evt
@ -125,7 +125,7 @@ func (v *tableView) activateCmd(evt *tcell.EventKey) *tcell.EventKey {
} }
v.app.flash(flashInfo, "Filtering...") v.app.flash(flashInfo, "Filtering...")
log.Info("Entering filtering mode...") log.Info().Msg("Entering filtering mode...")
v.cmdBuff.reset() v.cmdBuff.reset()
v.cmdBuff.setActive(true) v.cmdBuff.setActive(true)
return nil return nil

View File

@ -5,7 +5,8 @@ import (
"github.com/derailed/k9s/internal/cmd" "github.com/derailed/k9s/internal/cmd"
"github.com/derailed/k9s/internal/config" "github.com/derailed/k9s/internal/config"
log "github.com/sirupsen/logrus" "github.com/rs/zerolog"
"github.com/rs/zerolog/log"
_ "k8s.io/client-go/plugin/pkg/client/auth" _ "k8s.io/client-go/plugin/pkg/client/auth"
) )
@ -14,8 +15,7 @@ func init() {
mod := os.O_CREATE | os.O_APPEND | os.O_WRONLY mod := os.O_CREATE | os.O_APPEND | os.O_WRONLY
if file, err := os.OpenFile(config.K9sLogs, mod, config.DefaultFileMod); err == nil { if file, err := os.OpenFile(config.K9sLogs, mod, config.DefaultFileMod); err == nil {
log.SetOutput(file) log.Logger = log.Output(zerolog.ConsoleWriter{Out: file})
log.SetFormatter(&log.TextFormatter{FullTimestamp: true, ForceColors: true})
} else { } else {
panic(err) panic(err)
} }