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
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
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/peterbourgon/diskv v2.0.1+incompatible // indirect
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/pflag v1.0.3 // indirect
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-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
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/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
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/k8s"
"github.com/derailed/k9s/internal/views"
log "github.com/sirupsen/logrus"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions"
)
@ -55,7 +56,7 @@ func init() {
}
func initK9s() {
log.Info("🐶 K9s starting up...")
log.Info().Msg("🐶 K9s starting up...")
// Load K9s config file...
cfg := k8s.NewConfig(k8sFlags)
@ -64,14 +65,14 @@ func initK9s() {
// Init K8s connection...
k8s.InitConnectionOrDie(cfg)
log.Info("✅ Kubernetes connectivity")
log.Info().Msg("✅ Kubernetes connectivity")
config.Root.Save()
}
func initK9sConfig() {
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
@ -93,7 +94,7 @@ func initK9sConfig() {
config.Root.SetActiveNamespace(cfg.Contexts[ctx].Namespace)
}
}
log.Debugf("Active Context `%v`", ctx)
log.Debug().Msgf("Active Context `%v`", ctx)
if isSet(k8sFlags.Namespace) {
config.Root.SetActiveNamespace(*k8sFlags.Namespace)
@ -120,16 +121,27 @@ func isSet(s *string) bool {
// Execute root command
func Execute() {
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) {
level, err := log.ParseLevel(logLevel)
if err != nil {
level = log.DebugLevel
}
log.SetLevel(level)
zerolog.SetGlobalLevel(parseLevel(logLevel))
initK9s()
@ -140,7 +152,7 @@ func run(cmd *cobra.Command, args []string) {
clearScreen()
if err := recover(); err != nil {
app.Stop()
fmt.Println(err)
log.Error().Msgf("Boom! %#v", err)
debug.PrintStack()
}
}()

View File

@ -10,7 +10,7 @@ import (
"path/filepath"
"github.com/derailed/k9s/internal/resource"
log "github.com/sirupsen/logrus"
"github.com/rs/zerolog/log"
"gopkg.in/yaml.v2"
)
@ -76,11 +76,11 @@ func (c *Config) FavNamespaces() []string {
// SetActiveNamespace set the active namespace in the current cluster.
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 {
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")
}
@ -117,7 +117,7 @@ func (c *Config) Load(path string) error {
// Save configuration to disk.
func (c *Config) Save() error {
log.Debugf("[Config] Saving configuration...")
log.Debug().Msg("[Config] Saving configuration...")
c.Validate()
return c.SaveFile(K9sConfigFile)
}
@ -127,7 +127,7 @@ func (c *Config) SaveFile(path string) error {
EnsurePath(path, DefaultDirMod)
cfg, err := yaml.Marshal(c)
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 ioutil.WriteFile(path, cfg, 0644)
@ -140,9 +140,9 @@ func (c *Config) Validate() {
// Dump debug...
func (c *Config) Dump(msg string) {
log.Debug(msg)
log.Debugf("Current Context: %s\n", c.K9s.CurrentCluster)
log.Debug().Msg(msg)
log.Debug().Msgf("Current Context: %s\n", c.K9s.CurrentCluster)
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"
m "github.com/petergtz/pegomock"
"github.com/rs/zerolog"
"github.com/stretchr/testify/assert"
)
func init() {
zerolog.SetGlobalLevel(zerolog.FatalLevel)
}
func TestConfigValidate(t *testing.T) {
setup(t)

View File

@ -5,7 +5,7 @@ import (
"os/user"
"path/filepath"
log "github.com/sirupsen/logrus"
"github.com/rs/zerolog/log"
v1 "k8s.io/api/core/v1"
)
@ -56,7 +56,7 @@ func EnsurePath(path string, mod os.FileMode) {
dir := filepath.Dir(path)
if _, err := os.Stat(dir); os.IsNotExist(err) {
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)
}
}

View File

@ -1,7 +1,7 @@
package config
import (
log "github.com/sirupsen/logrus"
"github.com/rs/zerolog/log"
)
const (
@ -27,20 +27,20 @@ func NewNamespace() *Namespace {
// Validate a namespace is setup correctly
func (n *Namespace) Validate(ks KubeSettings) {
log.Debug("Validating favorites...", n.Active)
log.Debug().Msgf("Validating favorites... %s", n.Active)
nn, err := ks.NamespaceNames()
if err != nil {
return
}
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
}
for _, ns := range n.Favorites {
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)
}
}
@ -48,7 +48,7 @@ func (n *Namespace) Validate(ks KubeSettings) {
// SetActive set the active namespace.
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.addFavNS(ns)
return nil

View File

@ -4,7 +4,7 @@ import (
"errors"
"fmt"
log "github.com/sirupsen/logrus"
"github.com/rs/zerolog/log"
v1 "k8s.io/api/core/v1"
"k8s.io/cli-runtime/pkg/genericclioptions"
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.
func (c *Config) RawConfig() (clientcmdapi.Config, error) {
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.reset()
}
@ -248,7 +248,7 @@ func (c *Config) RawConfig() (clientcmdapi.Config, error) {
if err := c.configFromFlags(); err != nil {
return clientcmdapi.Config{}, err
}
log.Debugf("Reloading RawConfig...")
log.Debug().Msg("Reloading RawConfig...")
cfg, err := c.clientConfig.RawConfig()
if err != nil {
return cfg, err
@ -269,7 +269,7 @@ func (c *Config) RESTConfig() (*restclient.Config, error) {
if err != nil {
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
}

View File

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

View File

@ -38,5 +38,5 @@ func (*HPA) List(ns string) (Collection, error) {
// Delete a service
func (*HPA) Delete(ns, n string) error {
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"
"strings"
log "github.com/sirupsen/logrus"
"github.com/rs/zerolog/log"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
restclient "k8s.io/client-go/rest"
@ -53,7 +53,7 @@ func (j *Job) Containers(ns, n string, includeInit bool) ([]string, error) {
if err != nil {
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)
}
@ -63,7 +63,6 @@ func (j *Job) Logs(ns, n, co string, lines int64, prev bool) *restclient.Request
if err != nil {
return nil
}
log.Println("Logs found assoc pod", pod)
return NewPod().(Loggable).Logs(ns, pod, co, lines, prev)
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,7 +8,7 @@ import (
"time"
"github.com/derailed/k9s/internal/k8s"
log "github.com/sirupsen/logrus"
"github.com/rs/zerolog/log"
v1 "k8s.io/api/core/v1"
)
@ -86,7 +86,7 @@ func (r *Pod) NewInstance(i interface{}) Columnar {
po := ptr.(v1.Pod)
pod.instance = &po
default:
log.Fatalf("Unknown %#v", i)
log.Fatal().Msgf("Unknown %#v", i)
}
pod.path = r.namespacedName(pod.instance.ObjectMeta)
return pod
@ -169,7 +169,7 @@ func (r *Pod) List(ns string) (Columnars, error) {
metrics, err := r.metricSvc.PodMetrics()
if err != nil {
log.Warn(err)
log.Error().Err(err)
}
cc := make(Columnars, 0, len(ii))
@ -221,7 +221,7 @@ func (r *Pod) Fields(ns string) Row {
r.metrics.CPU,
r.metrics.Mem,
i.Status.PodIP,
i.Status.HostIP,
i.Spec.NodeName,
string(i.Status.QOSClass),
toAge(i.ObjectMeta.CreationTimestamp),
)
@ -231,15 +231,6 @@ func (r *Pod) Fields(ns string) Row {
func (r *Pod) ExtFields() Properties {
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{
"Priority": strconv.Itoa(int(*i.Spec.Priority)),
"Priority Class": missing(i.Spec.PriorityClassName),
@ -249,22 +240,9 @@ func (r *Pod) ExtFields() Properties {
"Init Containers": r.toContainers(i.Spec.InitContainers),
"Node Selectors": mapToStr(i.Spec.NodeSelector),
"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{} {
m := make(map[string]interface{}, len(vv))
for _, v := range vv {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,7 +8,7 @@ import (
"github.com/derailed/k9s/internal/config"
"github.com/derailed/tview"
"github.com/gdamore/tcell"
log "github.com/sirupsen/logrus"
"github.com/rs/zerolog/log"
"k8s.io/cli-runtime/pkg/genericclioptions"
)
@ -136,7 +136,7 @@ func (a *appView) keyboard(evt *tcell.EventKey) *tcell.EventKey {
key = tcell.Key(evt.Rune())
}
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 evt
@ -178,8 +178,11 @@ func (a *appView) gotoCmd(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...")
log.Debug("Entering app command mode...")
log.Debug().Msg("Entering app command mode...")
a.cmdBuff.setActive(true)
a.cmdBuff.clear()
return nil

View File

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

View File

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

View File

@ -10,13 +10,13 @@ import (
"strings"
"syscall"
log "github.com/sirupsen/logrus"
"github.com/rs/zerolog/log"
)
func runK(app *appView, args ...string) bool {
bin, err := exec.LookPath("kubectl")
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
}
@ -31,7 +31,7 @@ func runK(app *appView, args ...string) bool {
}
}
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())
}
})
@ -40,7 +40,7 @@ func runK(app *appView, args ...string) bool {
func run1(app *appView, bin string, args ...string) bool {
return app.Suspend(func() {
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())
}
})
@ -48,7 +48,7 @@ func run1(app *appView, bin string, args ...string) bool {
func execute(bin string, args ...string) error {
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())
defer cancel()
@ -56,14 +56,14 @@ func execute(bin string, args ...string) error {
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
go func() {
<-sigChan
log.Debug("Command canceled with signal!")
log.Debug().Msg("Command canceled with signal!")
cancel()
}()
cmd := exec.Command(bin, args...)
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
err := cmd.Run()
log.Debug("Command return status ", err)
log.Debug().Msgf("Command return status %v", err)
select {
case <-ctx.Done():
return errors.New("canceled by operator")

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -14,7 +14,7 @@ import (
"github.com/derailed/k9s/internal/resource"
"github.com/derailed/tview"
"github.com/gdamore/tcell"
log "github.com/sirupsen/logrus"
"github.com/rs/zerolog/log"
)
const noSelection = ""
@ -74,7 +74,7 @@ func (v *resourceView) init(ctx context.Context, ns string) {
for {
select {
case <-ctx.Done():
log.Debugf("%s watcher canceled!", v.title)
log.Debug().Msgf("%s watcher canceled!", v.title)
return
case <-time.After(time.Duration(initTick) * time.Second):
v.refresh()
@ -118,6 +118,12 @@ func (v *resourceView) hints() hints {
// ----------------------------------------------------------------------------
// 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 {
v.switchPage(v.list.GetName())
return nil
@ -145,7 +151,7 @@ func (v *resourceView) describeCmd(evt *tcell.EventKey) *tcell.EventKey {
raw, err := v.list.Resource().Describe(v.title, sel)
if err != nil {
v.app.flash(flashErr, "Unable to describeCmd this resource", err.Error())
log.Error(err)
log.Error().Err(err)
return evt
}
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)
if err != nil {
v.app.flash(flashErr, "Unable to marshal resource", err.Error())
log.Error(err)
log.Error().Err(err)
return evt
}
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) {
aa[KeyE] = newKeyAction("Edit", v.editCmd)
}

View File

@ -9,7 +9,7 @@ import (
"github.com/derailed/k9s/internal/resource"
"github.com/derailed/tview"
"github.com/gdamore/tcell"
log "github.com/sirupsen/logrus"
"github.com/rs/zerolog/log"
)
const (
@ -83,7 +83,7 @@ func (v *tableView) keyboard(evt *tcell.EventKey) *tcell.EventKey {
}
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 evt
@ -125,7 +125,7 @@ func (v *tableView) activateCmd(evt *tcell.EventKey) *tcell.EventKey {
}
v.app.flash(flashInfo, "Filtering...")
log.Info("Entering filtering mode...")
log.Info().Msg("Entering filtering mode...")
v.cmdBuff.reset()
v.cmdBuff.setActive(true)
return nil

View File

@ -5,7 +5,8 @@ import (
"github.com/derailed/k9s/internal/cmd"
"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"
)
@ -14,8 +15,7 @@ func init() {
mod := os.O_CREATE | os.O_APPEND | os.O_WRONLY
if file, err := os.OpenFile(config.K9sLogs, mod, config.DefaultFileMod); err == nil {
log.SetOutput(file)
log.SetFormatter(&log.TextFormatter{FullTimestamp: true, ForceColors: true})
log.Logger = log.Output(zerolog.ConsoleWriter{Out: file})
} else {
panic(err)
}