added columns for jobs
parent
1562b6255e
commit
a71f23d3aa
3
Makefile
3
Makefile
|
|
@ -6,6 +6,9 @@ DATE := $(shell date +%FT%T%Z)
|
||||||
|
|
||||||
default: help
|
default: help
|
||||||
|
|
||||||
|
test: ## Run all tests
|
||||||
|
@go test ./...
|
||||||
|
|
||||||
cover: ## Run test coverage suite
|
cover: ## Run test coverage suite
|
||||||
@go test ./... --coverprofile=cov.out
|
@go test ./... --coverprofile=cov.out
|
||||||
@go tool cover --html=cov.out
|
@go tool cover --html=cov.out
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
# Release v0.3.1
|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
|
1. Refactored a lot of code! So please watch for disturbence in the force!
|
||||||
|
1. Changed cronjob and job aliases names to `cj` and `jo` respectively
|
||||||
|
1. *JobView*: Added new columns
|
||||||
|
1. Completions
|
||||||
|
2. Containers
|
||||||
|
3. Images
|
||||||
|
1. *NodeView* Added the following columns:
|
||||||
|
1. Available CPU/Mem
|
||||||
|
2. Capacity CPU/Mem
|
||||||
|
1. *NodeView* Added sort fields for cpu and mem
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Resolved Bugs
|
||||||
|
|
||||||
|
+ [Issue #133](https://github.com/derailed/k9s/issues/133)
|
||||||
|
+ [Issue #132](https://github.com/derailed/k9s/issues/132)
|
||||||
|
+ [Issue #129](https://github.com/derailed/k9s/issues/129) The easiest bug fix to date ;)
|
||||||
19
cmd/info.go
19
cmd/info.go
|
|
@ -5,6 +5,7 @@ import (
|
||||||
|
|
||||||
"github.com/derailed/k9s/internal/config"
|
"github.com/derailed/k9s/internal/config"
|
||||||
"github.com/derailed/k9s/internal/printer"
|
"github.com/derailed/k9s/internal/printer"
|
||||||
|
"github.com/derailed/k9s/internal/views"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -14,11 +15,19 @@ func infoCmd() *cobra.Command {
|
||||||
Short: "Print configuration information",
|
Short: "Print configuration information",
|
||||||
Long: "Print configuration information",
|
Long: "Print configuration information",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
fmt.Printf(printer.Colorize(fmt.Sprintf("%-15s", "Configuration:"), printer.ColorMagenta))
|
printInfo()
|
||||||
fmt.Println(printer.Colorize(config.K9sConfigFile, printer.ColorDarkGray))
|
|
||||||
|
|
||||||
fmt.Printf(printer.Colorize(fmt.Sprintf("%-15s", "Logs:"), printer.ColorMagenta))
|
|
||||||
fmt.Println(printer.Colorize(config.K9sLogs, printer.ColorDarkGray))
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func printInfo() {
|
||||||
|
for _, l := range views.LogoSmall {
|
||||||
|
fmt.Println(printer.Colorize(l, printer.ColorCyan))
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Printf(printer.Colorize(fmt.Sprintf("%-15s", "Configuration:"), printer.ColorCyan))
|
||||||
|
fmt.Println(printer.Colorize(config.K9sConfigFile, printer.ColorWhite))
|
||||||
|
|
||||||
|
fmt.Printf(printer.Colorize(fmt.Sprintf("%-15s", "Logs:"), printer.ColorCyan))
|
||||||
|
fmt.Println(printer.Colorize(config.K9sLogs, printer.ColorWhite))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ func run(cmd *cobra.Command, args []string) {
|
||||||
defer func() {
|
defer func() {
|
||||||
clearScreen()
|
clearScreen()
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
log.Error().Msgf("%v", err)
|
log.Error().Msgf("Boom! %v", err)
|
||||||
log.Error().Msg(string(debug.Stack()))
|
log.Error().Msg(string(debug.Stack()))
|
||||||
fmt.Printf(printer.Colorize("Boom!! ", printer.ColorRed))
|
fmt.Printf(printer.Colorize("Boom!! ", printer.ColorRed))
|
||||||
fmt.Println(printer.Colorize(fmt.Sprintf("%v.", err), printer.ColorDarkGray))
|
fmt.Println(printer.Colorize(fmt.Sprintf("%v.", err), printer.ColorDarkGray))
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import "github.com/derailed/k9s/internal/k8s"
|
|
||||||
|
|
||||||
// Cluster tracks K9s cluster configuration.
|
// Cluster tracks K9s cluster configuration.
|
||||||
type Cluster struct {
|
type Cluster struct {
|
||||||
Namespace *Namespace `yaml:"namespace"`
|
Namespace *Namespace `yaml:"namespace"`
|
||||||
|
|
@ -14,7 +12,7 @@ func NewCluster() *Cluster {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate a cluster config.
|
// Validate a cluster config.
|
||||||
func (c *Cluster) Validate(conn k8s.Connection, ks KubeSettings) {
|
func (c *Cluster) Validate(conn Connection, ks KubeSettings) {
|
||||||
if c.Namespace == nil {
|
if c.Namespace == nil {
|
||||||
c.Namespace = NewNamespace()
|
c.Namespace = NewNamespace()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,19 @@ 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/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestClusterValidate(t *testing.T) {
|
func TestClusterValidate(t *testing.T) {
|
||||||
setup(t)
|
mc := NewMockConnection()
|
||||||
|
m.When(mc.ValidNamespaces()).ThenReturn(namespaces(), nil)
|
||||||
|
|
||||||
ksMock := NewMockKubeSettings()
|
mk := NewMockKubeSettings()
|
||||||
m.When(ksMock.NamespaceNames()).ThenReturn([]string{"ns1", "ns2", "default"}, nil)
|
m.When(mk.NamespaceNames(namespaces())).ThenReturn([]string{"ns1", "ns2", "default"})
|
||||||
|
|
||||||
c := config.NewCluster()
|
c := config.NewCluster()
|
||||||
c.Validate(ksMock)
|
c.Validate(mc, mk)
|
||||||
|
|
||||||
assert.Equal(t, "po", c.View.Active)
|
assert.Equal(t, "po", c.View.Active)
|
||||||
assert.Equal(t, "default", c.Namespace.Active)
|
assert.Equal(t, "default", c.Namespace.Active)
|
||||||
|
|
@ -24,16 +27,32 @@ func TestClusterValidate(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClusterValidateEmpty(t *testing.T) {
|
func TestClusterValidateEmpty(t *testing.T) {
|
||||||
setup(t)
|
mc := NewMockConnection()
|
||||||
|
m.When(mc.ValidNamespaces()).ThenReturn(namespaces(), nil)
|
||||||
|
|
||||||
ksMock := NewMockKubeSettings()
|
mk := NewMockKubeSettings()
|
||||||
m.When(ksMock.NamespaceNames()).ThenReturn([]string{"ns1", "ns2", "default"}, nil)
|
m.When(mk.NamespaceNames(namespaces())).ThenReturn([]string{"ns1", "ns2", "default"})
|
||||||
|
|
||||||
var c config.Cluster
|
var c config.Cluster
|
||||||
c.Validate(ksMock)
|
c.Validate(mc, mk)
|
||||||
|
|
||||||
assert.Equal(t, "po", c.View.Active)
|
assert.Equal(t, "po", c.View.Active)
|
||||||
assert.Equal(t, "default", c.Namespace.Active)
|
assert.Equal(t, "default", c.Namespace.Active)
|
||||||
assert.Equal(t, 1, len(c.Namespace.Favorites))
|
assert.Equal(t, 1, len(c.Namespace.Favorites))
|
||||||
assert.Equal(t, []string{"default"}, c.Namespace.Favorites)
|
assert.Equal(t, []string{"default"}, c.Namespace.Favorites)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func namespaces() []v1.Namespace {
|
||||||
|
return []v1.Namespace{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "default",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "fred",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,21 +26,26 @@ var (
|
||||||
K9sLogs = filepath.Join(os.TempDir(), fmt.Sprintf("k9s-%s.log", mustK9sUser()))
|
K9sLogs = filepath.Join(os.TempDir(), fmt.Sprintf("k9s-%s.log", mustK9sUser()))
|
||||||
)
|
)
|
||||||
|
|
||||||
// KubeSettings exposes kubeconfig context informations.
|
type (
|
||||||
type KubeSettings interface {
|
// Connection present a kubernetes api server connection.
|
||||||
|
Connection k8s.Connection
|
||||||
|
|
||||||
|
// KubeSettings exposes kubeconfig context informations.
|
||||||
|
KubeSettings interface {
|
||||||
CurrentContextName() (string, error)
|
CurrentContextName() (string, error)
|
||||||
CurrentClusterName() (string, error)
|
CurrentClusterName() (string, error)
|
||||||
CurrentNamespaceName() (string, error)
|
CurrentNamespaceName() (string, error)
|
||||||
ClusterNames() ([]string, error)
|
ClusterNames() ([]string, error)
|
||||||
NamespaceNames(nn []v1.Namespace) []string
|
NamespaceNames(nn []v1.Namespace) []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config tracks K9s configuration options.
|
// Config tracks K9s configuration options.
|
||||||
type Config struct {
|
Config struct {
|
||||||
K9s *K9s `yaml:"k9s"`
|
K9s *K9s `yaml:"k9s"`
|
||||||
client k8s.Connection
|
client Connection
|
||||||
settings KubeSettings
|
settings KubeSettings
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// NewConfig creates a new default config.
|
// NewConfig creates a new default config.
|
||||||
func NewConfig(ks KubeSettings) *Config {
|
func NewConfig(ks KubeSettings) *Config {
|
||||||
|
|
@ -135,12 +140,12 @@ func (c *Config) SetActiveView(view string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetConnection return an api server connection.
|
// GetConnection return an api server connection.
|
||||||
func (c *Config) GetConnection() k8s.Connection {
|
func (c *Config) GetConnection() Connection {
|
||||||
return c.client
|
return c.client
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetConnection set an api server connection.
|
// SetConnection set an api server connection.
|
||||||
func (c *Config) SetConnection(conn k8s.Connection) {
|
func (c *Config) SetConnection(conn Connection) {
|
||||||
c.client = conn
|
c.client = conn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,20 +17,20 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigValidate(t *testing.T) {
|
func TestConfigValidate(t *testing.T) {
|
||||||
setup(t)
|
mc := NewMockConnection()
|
||||||
|
m.When(mc.ValidNamespaces()).ThenReturn(namespaces(), nil)
|
||||||
|
mk := NewMockKubeSettings()
|
||||||
|
m.When(mk.ClusterNames()).ThenReturn([]string{"c1", "c2"}, nil)
|
||||||
|
|
||||||
ksMock := NewMockKubeSettings()
|
cfg := config.NewConfig(mk)
|
||||||
m.When(ksMock.NamespaceNames()).ThenReturn([]string{"ns1", "ns2", "default"}, nil)
|
cfg.SetConnection(mc)
|
||||||
m.When(ksMock.ClusterNames()).ThenReturn([]string{"c1", "c2"}, nil)
|
|
||||||
|
|
||||||
cfg := config.NewConfig(ksMock)
|
|
||||||
assert.Nil(t, cfg.Load("test_assets/k9s.yml"))
|
assert.Nil(t, cfg.Load("test_assets/k9s.yml"))
|
||||||
cfg.Validate()
|
cfg.Validate()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigLoad(t *testing.T) {
|
func TestConfigLoad(t *testing.T) {
|
||||||
ksMock := NewMockKubeSettings()
|
mk := NewMockKubeSettings()
|
||||||
cfg := config.NewConfig(ksMock)
|
cfg := config.NewConfig(mk)
|
||||||
assert.Nil(t, cfg.Load("test_assets/k9s.yml"))
|
assert.Nil(t, cfg.Load("test_assets/k9s.yml"))
|
||||||
|
|
||||||
assert.Equal(t, 2, cfg.K9s.RefreshRate)
|
assert.Equal(t, 2, cfg.K9s.RefreshRate)
|
||||||
|
|
@ -55,8 +55,8 @@ func TestConfigLoad(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigCurrentCluster(t *testing.T) {
|
func TestConfigCurrentCluster(t *testing.T) {
|
||||||
ksMock := NewMockKubeSettings()
|
mk := NewMockKubeSettings()
|
||||||
cfg := config.NewConfig(ksMock)
|
cfg := config.NewConfig(mk)
|
||||||
|
|
||||||
assert.Nil(t, cfg.Load("test_assets/k9s.yml"))
|
assert.Nil(t, cfg.Load("test_assets/k9s.yml"))
|
||||||
assert.NotNil(t, cfg.CurrentCluster())
|
assert.NotNil(t, cfg.CurrentCluster())
|
||||||
|
|
@ -65,8 +65,8 @@ func TestConfigCurrentCluster(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigActiveNamespace(t *testing.T) {
|
func TestConfigActiveNamespace(t *testing.T) {
|
||||||
ksMock := NewMockKubeSettings()
|
mk := NewMockKubeSettings()
|
||||||
cfg := config.NewConfig(ksMock)
|
cfg := config.NewConfig(mk)
|
||||||
|
|
||||||
assert.Nil(t, cfg.Load("test_assets/k9s.yml"))
|
assert.Nil(t, cfg.Load("test_assets/k9s.yml"))
|
||||||
assert.Equal(t, "kube-system", cfg.ActiveNamespace())
|
assert.Equal(t, "kube-system", cfg.ActiveNamespace())
|
||||||
|
|
@ -78,8 +78,8 @@ func TestConfigActiveNamespaceBlank(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigSetActiveNamespace(t *testing.T) {
|
func TestConfigSetActiveNamespace(t *testing.T) {
|
||||||
ksMock := NewMockKubeSettings()
|
mk := NewMockKubeSettings()
|
||||||
cfg := config.NewConfig(ksMock)
|
cfg := config.NewConfig(mk)
|
||||||
|
|
||||||
assert.Nil(t, cfg.Load("test_assets/k9s.yml"))
|
assert.Nil(t, cfg.Load("test_assets/k9s.yml"))
|
||||||
cfg.SetActiveNamespace("default")
|
cfg.SetActiveNamespace("default")
|
||||||
|
|
@ -87,8 +87,8 @@ func TestConfigSetActiveNamespace(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigActiveView(t *testing.T) {
|
func TestConfigActiveView(t *testing.T) {
|
||||||
ksMock := NewMockKubeSettings()
|
mk := NewMockKubeSettings()
|
||||||
cfg := config.NewConfig(ksMock)
|
cfg := config.NewConfig(mk)
|
||||||
|
|
||||||
assert.Nil(t, cfg.Load("test_assets/k9s.yml"))
|
assert.Nil(t, cfg.Load("test_assets/k9s.yml"))
|
||||||
assert.Equal(t, "ctx", cfg.ActiveView())
|
assert.Equal(t, "ctx", cfg.ActiveView())
|
||||||
|
|
@ -100,8 +100,8 @@ func TestConfigActiveViewBlank(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigSetActiveView(t *testing.T) {
|
func TestConfigSetActiveView(t *testing.T) {
|
||||||
ksMock := NewMockKubeSettings()
|
mk := NewMockKubeSettings()
|
||||||
cfg := config.NewConfig(ksMock)
|
cfg := config.NewConfig(mk)
|
||||||
|
|
||||||
assert.Nil(t, cfg.Load("test_assets/k9s.yml"))
|
assert.Nil(t, cfg.Load("test_assets/k9s.yml"))
|
||||||
cfg.SetActiveView("po")
|
cfg.SetActiveView("po")
|
||||||
|
|
@ -109,8 +109,8 @@ func TestConfigSetActiveView(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigFavNamespaces(t *testing.T) {
|
func TestConfigFavNamespaces(t *testing.T) {
|
||||||
ksMock := NewMockKubeSettings()
|
mk := NewMockKubeSettings()
|
||||||
cfg := config.NewConfig(ksMock)
|
cfg := config.NewConfig(mk)
|
||||||
|
|
||||||
assert.Nil(t, cfg.Load("test_assets/k9s.yml"))
|
assert.Nil(t, cfg.Load("test_assets/k9s.yml"))
|
||||||
expectedNS := []string{"default", "kube-public", "istio-system", "all", "kube-system"}
|
expectedNS := []string{"default", "kube-public", "istio-system", "all", "kube-system"}
|
||||||
|
|
@ -118,26 +118,30 @@ func TestConfigFavNamespaces(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigLoadOldCfg(t *testing.T) {
|
func TestConfigLoadOldCfg(t *testing.T) {
|
||||||
ksMock := NewMockKubeSettings()
|
mk := NewMockKubeSettings()
|
||||||
cfg := config.NewConfig(ksMock)
|
cfg := config.NewConfig(mk)
|
||||||
assert.Nil(t, cfg.Load("test_assets/k9s_old.yml"))
|
assert.Nil(t, cfg.Load("test_assets/k9s_old.yml"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigLoadCrap(t *testing.T) {
|
func TestConfigLoadCrap(t *testing.T) {
|
||||||
ksMock := NewMockKubeSettings()
|
mk := NewMockKubeSettings()
|
||||||
cfg := config.NewConfig(ksMock)
|
cfg := config.NewConfig(mk)
|
||||||
assert.NotNil(t, cfg.Load("test_assets/k9s_not_there.yml"))
|
assert.NotNil(t, cfg.Load("test_assets/k9s_not_there.yml"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigSaveFile(t *testing.T) {
|
func TestConfigSaveFile(t *testing.T) {
|
||||||
ksMock := NewMockKubeSettings()
|
mc := NewMockConnection()
|
||||||
m.When(ksMock.CurrentContextName()).ThenReturn("minikube", nil)
|
m.When(mc.ValidNamespaces()).ThenReturn(namespaces(), nil)
|
||||||
m.When(ksMock.CurrentClusterName()).ThenReturn("minikube", nil)
|
|
||||||
m.When(ksMock.CurrentNamespaceName()).ThenReturn("default", nil)
|
|
||||||
m.When(ksMock.ClusterNames()).ThenReturn([]string{"minikube", "fred", "blee"}, nil)
|
|
||||||
m.When(ksMock.NamespaceNames()).ThenReturn([]string{"default"}, nil)
|
|
||||||
|
|
||||||
cfg := config.NewConfig(ksMock)
|
mk := NewMockKubeSettings()
|
||||||
|
m.When(mk.CurrentContextName()).ThenReturn("minikube", nil)
|
||||||
|
m.When(mk.CurrentClusterName()).ThenReturn("minikube", nil)
|
||||||
|
m.When(mk.CurrentNamespaceName()).ThenReturn("default", nil)
|
||||||
|
m.When(mk.ClusterNames()).ThenReturn([]string{"minikube", "fred", "blee"}, nil)
|
||||||
|
m.When(mk.NamespaceNames(namespaces())).ThenReturn([]string{"default"})
|
||||||
|
|
||||||
|
cfg := config.NewConfig(mk)
|
||||||
|
cfg.SetConnection(mc)
|
||||||
cfg.Load("test_assets/k9s.yml")
|
cfg.Load("test_assets/k9s.yml")
|
||||||
cfg.K9s.RefreshRate = 100
|
cfg.K9s.RefreshRate = 100
|
||||||
cfg.K9s.LogBufferSize = 500
|
cfg.K9s.LogBufferSize = 500
|
||||||
|
|
@ -155,14 +159,18 @@ func TestConfigSaveFile(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigReset(t *testing.T) {
|
func TestConfigReset(t *testing.T) {
|
||||||
ksMock := NewMockKubeSettings()
|
mc := NewMockConnection()
|
||||||
m.When(ksMock.CurrentContextName()).ThenReturn("blee", nil)
|
m.When(mc.ValidNamespaces()).ThenReturn(namespaces(), nil)
|
||||||
m.When(ksMock.CurrentClusterName()).ThenReturn("blee", nil)
|
|
||||||
m.When(ksMock.CurrentNamespaceName()).ThenReturn("default", nil)
|
|
||||||
m.When(ksMock.ClusterNames()).ThenReturn([]string{"blee"}, nil)
|
|
||||||
m.When(ksMock.NamespaceNames()).ThenReturn([]string{"default"}, nil)
|
|
||||||
|
|
||||||
cfg := config.NewConfig(ksMock)
|
mk := NewMockKubeSettings()
|
||||||
|
m.When(mk.CurrentContextName()).ThenReturn("blee", nil)
|
||||||
|
m.When(mk.CurrentClusterName()).ThenReturn("blee", nil)
|
||||||
|
m.When(mk.CurrentNamespaceName()).ThenReturn("default", nil)
|
||||||
|
m.When(mk.ClusterNames()).ThenReturn([]string{"blee"}, nil)
|
||||||
|
m.When(mk.NamespaceNames(namespaces())).ThenReturn([]string{"default"})
|
||||||
|
|
||||||
|
cfg := config.NewConfig(mk)
|
||||||
|
cfg.SetConnection(mc)
|
||||||
cfg.Load("test_assets/k9s.yml")
|
cfg.Load("test_assets/k9s.yml")
|
||||||
cfg.Reset()
|
cfg.Reset()
|
||||||
cfg.Validate()
|
cfg.Validate()
|
||||||
|
|
@ -178,7 +186,7 @@ func TestConfigReset(t *testing.T) {
|
||||||
|
|
||||||
// Helpers...
|
// Helpers...
|
||||||
|
|
||||||
func setup(t *testing.T) {
|
func TestSetup(t *testing.T) {
|
||||||
m.RegisterMockTestingT(t)
|
m.RegisterMockTestingT(t)
|
||||||
m.RegisterMockFailHandler(func(m string, i ...int) {
|
m.RegisterMockFailHandler(func(m string, i ...int) {
|
||||||
fmt.Println("Boom!", m, i)
|
fmt.Println("Boom!", m, i)
|
||||||
|
|
|
||||||
|
|
@ -9,15 +9,14 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestK9sValidate(t *testing.T) {
|
func TestK9sValidate(t *testing.T) {
|
||||||
setup(t)
|
mc := NewMockConnection()
|
||||||
|
mk := NewMockKubeSettings()
|
||||||
ksMock := NewMockKubeSettings()
|
m.When(mk.CurrentContextName()).ThenReturn("ctx1", nil)
|
||||||
m.When(ksMock.CurrentContextName()).ThenReturn("ctx1", nil)
|
m.When(mk.CurrentClusterName()).ThenReturn("c1", nil)
|
||||||
m.When(ksMock.CurrentClusterName()).ThenReturn("c1", nil)
|
m.When(mk.ClusterNames()).ThenReturn([]string{"c1", "c2"}, nil)
|
||||||
m.When(ksMock.ClusterNames()).ThenReturn([]string{"c1", "c2"}, nil)
|
|
||||||
|
|
||||||
c := config.NewK9s()
|
c := config.NewK9s()
|
||||||
c.Validate(ksMock)
|
c.Validate(mc, mk)
|
||||||
|
|
||||||
assert.Equal(t, 2, c.RefreshRate)
|
assert.Equal(t, 2, c.RefreshRate)
|
||||||
assert.Equal(t, 1000, c.LogBufferSize)
|
assert.Equal(t, 1000, c.LogBufferSize)
|
||||||
|
|
@ -30,15 +29,14 @@ func TestK9sValidate(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestK9sValidateBlank(t *testing.T) {
|
func TestK9sValidateBlank(t *testing.T) {
|
||||||
setup(t)
|
mc := NewMockConnection()
|
||||||
|
mk := NewMockKubeSettings()
|
||||||
ksMock := NewMockKubeSettings()
|
m.When(mk.CurrentContextName()).ThenReturn("ctx1", nil)
|
||||||
m.When(ksMock.CurrentContextName()).ThenReturn("ctx1", nil)
|
m.When(mk.CurrentClusterName()).ThenReturn("c1", nil)
|
||||||
m.When(ksMock.CurrentClusterName()).ThenReturn("c1", nil)
|
m.When(mk.ClusterNames()).ThenReturn([]string{"c1", "c2"}, nil)
|
||||||
m.When(ksMock.ClusterNames()).ThenReturn([]string{"c1", "c2"}, nil)
|
|
||||||
|
|
||||||
var c config.K9s
|
var c config.K9s
|
||||||
c.Validate(ksMock)
|
c.Validate(mc, mk)
|
||||||
|
|
||||||
assert.Equal(t, 2, c.RefreshRate)
|
assert.Equal(t, 2, c.RefreshRate)
|
||||||
assert.Equal(t, 1000, c.LogBufferSize)
|
assert.Equal(t, 1000, c.LogBufferSize)
|
||||||
|
|
@ -51,8 +49,6 @@ func TestK9sValidateBlank(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestK9sActiveClusterZero(t *testing.T) {
|
func TestK9sActiveClusterZero(t *testing.T) {
|
||||||
setup(t)
|
|
||||||
|
|
||||||
c := config.NewK9s()
|
c := config.NewK9s()
|
||||||
c.CurrentCluster = "fred"
|
c.CurrentCluster = "fred"
|
||||||
cl := c.ActiveCluster()
|
cl := c.ActiveCluster()
|
||||||
|
|
@ -62,18 +58,14 @@ func TestK9sActiveClusterZero(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestK9sActiveClusterBlank(t *testing.T) {
|
func TestK9sActiveClusterBlank(t *testing.T) {
|
||||||
setup(t)
|
|
||||||
|
|
||||||
var c config.K9s
|
var c config.K9s
|
||||||
cl := c.ActiveCluster()
|
cl := c.ActiveCluster()
|
||||||
assert.Nil(t, cl)
|
assert.Nil(t, cl)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestK9sActiveCluster(t *testing.T) {
|
func TestK9sActiveCluster(t *testing.T) {
|
||||||
setup(t)
|
mk := NewMockKubeSettings()
|
||||||
|
cfg := config.NewConfig(mk)
|
||||||
ksMock := NewMockKubeSettings()
|
|
||||||
cfg := config.NewConfig(ksMock)
|
|
||||||
assert.Nil(t, cfg.Load("test_assets/k9s.yml"))
|
assert.Nil(t, cfg.Load("test_assets/k9s.yml"))
|
||||||
|
|
||||||
cl := cfg.K9s.ActiveCluster()
|
cl := cfg.K9s.ActiveCluster()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,444 @@
|
||||||
|
// Code generated by pegomock. DO NOT EDIT.
|
||||||
|
// Source: github.com/derailed/k9s/internal/config (interfaces: Connection)
|
||||||
|
|
||||||
|
package config_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
k8s "github.com/derailed/k9s/internal/k8s"
|
||||||
|
pegomock "github.com/petergtz/pegomock"
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
|
dynamic "k8s.io/client-go/dynamic"
|
||||||
|
kubernetes "k8s.io/client-go/kubernetes"
|
||||||
|
rest "k8s.io/client-go/rest"
|
||||||
|
versioned "k8s.io/metrics/pkg/client/clientset/versioned"
|
||||||
|
"reflect"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MockConnection struct {
|
||||||
|
fail func(message string, callerSkip ...int)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMockConnection() *MockConnection {
|
||||||
|
return &MockConnection{fail: pegomock.GlobalFailHandler}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock *MockConnection) Config() *k8s.Config {
|
||||||
|
if mock == nil {
|
||||||
|
panic("mock must not be nil. Use myMock := NewMockConnection().")
|
||||||
|
}
|
||||||
|
params := []pegomock.Param{}
|
||||||
|
result := pegomock.GetGenericMockFrom(mock).Invoke("Config", params, []reflect.Type{reflect.TypeOf((**k8s.Config)(nil)).Elem()})
|
||||||
|
var ret0 *k8s.Config
|
||||||
|
if len(result) != 0 {
|
||||||
|
if result[0] != nil {
|
||||||
|
ret0 = result[0].(*k8s.Config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock *MockConnection) DialOrDie() kubernetes.Interface {
|
||||||
|
if mock == nil {
|
||||||
|
panic("mock must not be nil. Use myMock := NewMockConnection().")
|
||||||
|
}
|
||||||
|
params := []pegomock.Param{}
|
||||||
|
result := pegomock.GetGenericMockFrom(mock).Invoke("DialOrDie", params, []reflect.Type{reflect.TypeOf((*kubernetes.Interface)(nil)).Elem()})
|
||||||
|
var ret0 kubernetes.Interface
|
||||||
|
if len(result) != 0 {
|
||||||
|
if result[0] != nil {
|
||||||
|
ret0 = result[0].(kubernetes.Interface)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock *MockConnection) DynDialOrDie() dynamic.Interface {
|
||||||
|
if mock == nil {
|
||||||
|
panic("mock must not be nil. Use myMock := NewMockConnection().")
|
||||||
|
}
|
||||||
|
params := []pegomock.Param{}
|
||||||
|
result := pegomock.GetGenericMockFrom(mock).Invoke("DynDialOrDie", params, []reflect.Type{reflect.TypeOf((*dynamic.Interface)(nil)).Elem()})
|
||||||
|
var ret0 dynamic.Interface
|
||||||
|
if len(result) != 0 {
|
||||||
|
if result[0] != nil {
|
||||||
|
ret0 = result[0].(dynamic.Interface)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock *MockConnection) HasMetrics() bool {
|
||||||
|
if mock == nil {
|
||||||
|
panic("mock must not be nil. Use myMock := NewMockConnection().")
|
||||||
|
}
|
||||||
|
params := []pegomock.Param{}
|
||||||
|
result := pegomock.GetGenericMockFrom(mock).Invoke("HasMetrics", params, []reflect.Type{reflect.TypeOf((*bool)(nil)).Elem()})
|
||||||
|
var ret0 bool
|
||||||
|
if len(result) != 0 {
|
||||||
|
if result[0] != nil {
|
||||||
|
ret0 = result[0].(bool)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock *MockConnection) IsNamespaced(_param0 string) bool {
|
||||||
|
if mock == nil {
|
||||||
|
panic("mock must not be nil. Use myMock := NewMockConnection().")
|
||||||
|
}
|
||||||
|
params := []pegomock.Param{_param0}
|
||||||
|
result := pegomock.GetGenericMockFrom(mock).Invoke("IsNamespaced", params, []reflect.Type{reflect.TypeOf((*bool)(nil)).Elem()})
|
||||||
|
var ret0 bool
|
||||||
|
if len(result) != 0 {
|
||||||
|
if result[0] != nil {
|
||||||
|
ret0 = result[0].(bool)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock *MockConnection) MXDial() (*versioned.Clientset, error) {
|
||||||
|
if mock == nil {
|
||||||
|
panic("mock must not be nil. Use myMock := NewMockConnection().")
|
||||||
|
}
|
||||||
|
params := []pegomock.Param{}
|
||||||
|
result := pegomock.GetGenericMockFrom(mock).Invoke("MXDial", params, []reflect.Type{reflect.TypeOf((**versioned.Clientset)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
|
||||||
|
var ret0 *versioned.Clientset
|
||||||
|
var ret1 error
|
||||||
|
if len(result) != 0 {
|
||||||
|
if result[0] != nil {
|
||||||
|
ret0 = result[0].(*versioned.Clientset)
|
||||||
|
}
|
||||||
|
if result[1] != nil {
|
||||||
|
ret1 = result[1].(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock *MockConnection) NSDialOrDie() dynamic.NamespaceableResourceInterface {
|
||||||
|
if mock == nil {
|
||||||
|
panic("mock must not be nil. Use myMock := NewMockConnection().")
|
||||||
|
}
|
||||||
|
params := []pegomock.Param{}
|
||||||
|
result := pegomock.GetGenericMockFrom(mock).Invoke("NSDialOrDie", params, []reflect.Type{reflect.TypeOf((*dynamic.NamespaceableResourceInterface)(nil)).Elem()})
|
||||||
|
var ret0 dynamic.NamespaceableResourceInterface
|
||||||
|
if len(result) != 0 {
|
||||||
|
if result[0] != nil {
|
||||||
|
ret0 = result[0].(dynamic.NamespaceableResourceInterface)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock *MockConnection) RestConfigOrDie() *rest.Config {
|
||||||
|
if mock == nil {
|
||||||
|
panic("mock must not be nil. Use myMock := NewMockConnection().")
|
||||||
|
}
|
||||||
|
params := []pegomock.Param{}
|
||||||
|
result := pegomock.GetGenericMockFrom(mock).Invoke("RestConfigOrDie", params, []reflect.Type{reflect.TypeOf((**rest.Config)(nil)).Elem()})
|
||||||
|
var ret0 *rest.Config
|
||||||
|
if len(result) != 0 {
|
||||||
|
if result[0] != nil {
|
||||||
|
ret0 = result[0].(*rest.Config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock *MockConnection) SupportsResource(_param0 string) bool {
|
||||||
|
if mock == nil {
|
||||||
|
panic("mock must not be nil. Use myMock := NewMockConnection().")
|
||||||
|
}
|
||||||
|
params := []pegomock.Param{_param0}
|
||||||
|
result := pegomock.GetGenericMockFrom(mock).Invoke("SupportsResource", params, []reflect.Type{reflect.TypeOf((*bool)(nil)).Elem()})
|
||||||
|
var ret0 bool
|
||||||
|
if len(result) != 0 {
|
||||||
|
if result[0] != nil {
|
||||||
|
ret0 = result[0].(bool)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock *MockConnection) SwitchContextOrDie(_param0 string) {
|
||||||
|
if mock == nil {
|
||||||
|
panic("mock must not be nil. Use myMock := NewMockConnection().")
|
||||||
|
}
|
||||||
|
params := []pegomock.Param{_param0}
|
||||||
|
pegomock.GetGenericMockFrom(mock).Invoke("SwitchContextOrDie", params, []reflect.Type{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock *MockConnection) ValidNamespaces() ([]v1.Namespace, error) {
|
||||||
|
if mock == nil {
|
||||||
|
panic("mock must not be nil. Use myMock := NewMockConnection().")
|
||||||
|
}
|
||||||
|
params := []pegomock.Param{}
|
||||||
|
result := pegomock.GetGenericMockFrom(mock).Invoke("ValidNamespaces", params, []reflect.Type{reflect.TypeOf((*[]v1.Namespace)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
|
||||||
|
var ret0 []v1.Namespace
|
||||||
|
var ret1 error
|
||||||
|
if len(result) != 0 {
|
||||||
|
if result[0] != nil {
|
||||||
|
ret0 = result[0].([]v1.Namespace)
|
||||||
|
}
|
||||||
|
if result[1] != nil {
|
||||||
|
ret1 = result[1].(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock *MockConnection) VerifyWasCalledOnce() *VerifierConnection {
|
||||||
|
return &VerifierConnection{
|
||||||
|
mock: mock,
|
||||||
|
invocationCountMatcher: pegomock.Times(1),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock *MockConnection) VerifyWasCalled(invocationCountMatcher pegomock.Matcher) *VerifierConnection {
|
||||||
|
return &VerifierConnection{
|
||||||
|
mock: mock,
|
||||||
|
invocationCountMatcher: invocationCountMatcher,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock *MockConnection) VerifyWasCalledInOrder(invocationCountMatcher pegomock.Matcher, inOrderContext *pegomock.InOrderContext) *VerifierConnection {
|
||||||
|
return &VerifierConnection{
|
||||||
|
mock: mock,
|
||||||
|
invocationCountMatcher: invocationCountMatcher,
|
||||||
|
inOrderContext: inOrderContext,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock *MockConnection) VerifyWasCalledEventually(invocationCountMatcher pegomock.Matcher, timeout time.Duration) *VerifierConnection {
|
||||||
|
return &VerifierConnection{
|
||||||
|
mock: mock,
|
||||||
|
invocationCountMatcher: invocationCountMatcher,
|
||||||
|
timeout: timeout,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type VerifierConnection struct {
|
||||||
|
mock *MockConnection
|
||||||
|
invocationCountMatcher pegomock.Matcher
|
||||||
|
inOrderContext *pegomock.InOrderContext
|
||||||
|
timeout time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func (verifier *VerifierConnection) Config() *Connection_Config_OngoingVerification {
|
||||||
|
params := []pegomock.Param{}
|
||||||
|
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Config", params, verifier.timeout)
|
||||||
|
return &Connection_Config_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Connection_Config_OngoingVerification struct {
|
||||||
|
mock *MockConnection
|
||||||
|
methodInvocations []pegomock.MethodInvocation
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_Config_OngoingVerification) GetCapturedArguments() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_Config_OngoingVerification) GetAllCapturedArguments() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (verifier *VerifierConnection) DialOrDie() *Connection_DialOrDie_OngoingVerification {
|
||||||
|
params := []pegomock.Param{}
|
||||||
|
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "DialOrDie", params, verifier.timeout)
|
||||||
|
return &Connection_DialOrDie_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Connection_DialOrDie_OngoingVerification struct {
|
||||||
|
mock *MockConnection
|
||||||
|
methodInvocations []pegomock.MethodInvocation
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_DialOrDie_OngoingVerification) GetCapturedArguments() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_DialOrDie_OngoingVerification) GetAllCapturedArguments() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (verifier *VerifierConnection) DynDialOrDie() *Connection_DynDialOrDie_OngoingVerification {
|
||||||
|
params := []pegomock.Param{}
|
||||||
|
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "DynDialOrDie", params, verifier.timeout)
|
||||||
|
return &Connection_DynDialOrDie_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Connection_DynDialOrDie_OngoingVerification struct {
|
||||||
|
mock *MockConnection
|
||||||
|
methodInvocations []pegomock.MethodInvocation
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_DynDialOrDie_OngoingVerification) GetCapturedArguments() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_DynDialOrDie_OngoingVerification) GetAllCapturedArguments() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (verifier *VerifierConnection) HasMetrics() *Connection_HasMetrics_OngoingVerification {
|
||||||
|
params := []pegomock.Param{}
|
||||||
|
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "HasMetrics", params, verifier.timeout)
|
||||||
|
return &Connection_HasMetrics_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Connection_HasMetrics_OngoingVerification struct {
|
||||||
|
mock *MockConnection
|
||||||
|
methodInvocations []pegomock.MethodInvocation
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_HasMetrics_OngoingVerification) GetCapturedArguments() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_HasMetrics_OngoingVerification) GetAllCapturedArguments() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (verifier *VerifierConnection) IsNamespaced(_param0 string) *Connection_IsNamespaced_OngoingVerification {
|
||||||
|
params := []pegomock.Param{_param0}
|
||||||
|
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "IsNamespaced", params, verifier.timeout)
|
||||||
|
return &Connection_IsNamespaced_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Connection_IsNamespaced_OngoingVerification struct {
|
||||||
|
mock *MockConnection
|
||||||
|
methodInvocations []pegomock.MethodInvocation
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_IsNamespaced_OngoingVerification) GetCapturedArguments() string {
|
||||||
|
_param0 := c.GetAllCapturedArguments()
|
||||||
|
return _param0[len(_param0)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_IsNamespaced_OngoingVerification) GetAllCapturedArguments() (_param0 []string) {
|
||||||
|
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
|
||||||
|
if len(params) > 0 {
|
||||||
|
_param0 = make([]string, len(params[0]))
|
||||||
|
for u, param := range params[0] {
|
||||||
|
_param0[u] = param.(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (verifier *VerifierConnection) MXDial() *Connection_MXDial_OngoingVerification {
|
||||||
|
params := []pegomock.Param{}
|
||||||
|
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "MXDial", params, verifier.timeout)
|
||||||
|
return &Connection_MXDial_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Connection_MXDial_OngoingVerification struct {
|
||||||
|
mock *MockConnection
|
||||||
|
methodInvocations []pegomock.MethodInvocation
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_MXDial_OngoingVerification) GetCapturedArguments() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_MXDial_OngoingVerification) GetAllCapturedArguments() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (verifier *VerifierConnection) NSDialOrDie() *Connection_NSDialOrDie_OngoingVerification {
|
||||||
|
params := []pegomock.Param{}
|
||||||
|
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "NSDialOrDie", params, verifier.timeout)
|
||||||
|
return &Connection_NSDialOrDie_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Connection_NSDialOrDie_OngoingVerification struct {
|
||||||
|
mock *MockConnection
|
||||||
|
methodInvocations []pegomock.MethodInvocation
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_NSDialOrDie_OngoingVerification) GetCapturedArguments() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_NSDialOrDie_OngoingVerification) GetAllCapturedArguments() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (verifier *VerifierConnection) RestConfigOrDie() *Connection_RestConfigOrDie_OngoingVerification {
|
||||||
|
params := []pegomock.Param{}
|
||||||
|
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "RestConfigOrDie", params, verifier.timeout)
|
||||||
|
return &Connection_RestConfigOrDie_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Connection_RestConfigOrDie_OngoingVerification struct {
|
||||||
|
mock *MockConnection
|
||||||
|
methodInvocations []pegomock.MethodInvocation
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_RestConfigOrDie_OngoingVerification) GetCapturedArguments() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_RestConfigOrDie_OngoingVerification) GetAllCapturedArguments() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (verifier *VerifierConnection) SupportsResource(_param0 string) *Connection_SupportsResource_OngoingVerification {
|
||||||
|
params := []pegomock.Param{_param0}
|
||||||
|
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "SupportsResource", params, verifier.timeout)
|
||||||
|
return &Connection_SupportsResource_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Connection_SupportsResource_OngoingVerification struct {
|
||||||
|
mock *MockConnection
|
||||||
|
methodInvocations []pegomock.MethodInvocation
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_SupportsResource_OngoingVerification) GetCapturedArguments() string {
|
||||||
|
_param0 := c.GetAllCapturedArguments()
|
||||||
|
return _param0[len(_param0)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_SupportsResource_OngoingVerification) GetAllCapturedArguments() (_param0 []string) {
|
||||||
|
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
|
||||||
|
if len(params) > 0 {
|
||||||
|
_param0 = make([]string, len(params[0]))
|
||||||
|
for u, param := range params[0] {
|
||||||
|
_param0[u] = param.(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (verifier *VerifierConnection) SwitchContextOrDie(_param0 string) *Connection_SwitchContextOrDie_OngoingVerification {
|
||||||
|
params := []pegomock.Param{_param0}
|
||||||
|
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "SwitchContextOrDie", params, verifier.timeout)
|
||||||
|
return &Connection_SwitchContextOrDie_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Connection_SwitchContextOrDie_OngoingVerification struct {
|
||||||
|
mock *MockConnection
|
||||||
|
methodInvocations []pegomock.MethodInvocation
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_SwitchContextOrDie_OngoingVerification) GetCapturedArguments() string {
|
||||||
|
_param0 := c.GetAllCapturedArguments()
|
||||||
|
return _param0[len(_param0)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_SwitchContextOrDie_OngoingVerification) GetAllCapturedArguments() (_param0 []string) {
|
||||||
|
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
|
||||||
|
if len(params) > 0 {
|
||||||
|
_param0 = make([]string, len(params[0]))
|
||||||
|
for u, param := range params[0] {
|
||||||
|
_param0[u] = param.(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (verifier *VerifierConnection) ValidNamespaces() *Connection_ValidNamespaces_OngoingVerification {
|
||||||
|
params := []pegomock.Param{}
|
||||||
|
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "ValidNamespaces", params, verifier.timeout)
|
||||||
|
return &Connection_ValidNamespaces_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Connection_ValidNamespaces_OngoingVerification struct {
|
||||||
|
mock *MockConnection
|
||||||
|
methodInvocations []pegomock.MethodInvocation
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_ValidNamespaces_OngoingVerification) GetCapturedArguments() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_ValidNamespaces_OngoingVerification) GetAllCapturedArguments() {
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ package config_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
pegomock "github.com/petergtz/pegomock"
|
pegomock "github.com/petergtz/pegomock"
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
@ -93,23 +94,19 @@ func (mock *MockKubeSettings) CurrentNamespaceName() (string, error) {
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mock *MockKubeSettings) NamespaceNames() ([]string, error) {
|
func (mock *MockKubeSettings) NamespaceNames(_param0 []v1.Namespace) []string {
|
||||||
if mock == nil {
|
if mock == nil {
|
||||||
panic("mock must not be nil. Use myMock := NewMockKubeSettings().")
|
panic("mock must not be nil. Use myMock := NewMockKubeSettings().")
|
||||||
}
|
}
|
||||||
params := []pegomock.Param{}
|
params := []pegomock.Param{_param0}
|
||||||
result := pegomock.GetGenericMockFrom(mock).Invoke("NamespaceNames", params, []reflect.Type{reflect.TypeOf((*[]string)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
|
result := pegomock.GetGenericMockFrom(mock).Invoke("NamespaceNames", params, []reflect.Type{reflect.TypeOf((*[]string)(nil)).Elem()})
|
||||||
var ret0 []string
|
var ret0 []string
|
||||||
var ret1 error
|
|
||||||
if len(result) != 0 {
|
if len(result) != 0 {
|
||||||
if result[0] != nil {
|
if result[0] != nil {
|
||||||
ret0 = result[0].([]string)
|
ret0 = result[0].([]string)
|
||||||
}
|
}
|
||||||
if result[1] != nil {
|
|
||||||
ret1 = result[1].(error)
|
|
||||||
}
|
}
|
||||||
}
|
return ret0
|
||||||
return ret0, ret1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mock *MockKubeSettings) VerifyWasCalledOnce() *VerifierKubeSettings {
|
func (mock *MockKubeSettings) VerifyWasCalledOnce() *VerifierKubeSettings {
|
||||||
|
|
@ -217,8 +214,8 @@ func (c *KubeSettings_CurrentNamespaceName_OngoingVerification) GetCapturedArgum
|
||||||
func (c *KubeSettings_CurrentNamespaceName_OngoingVerification) GetAllCapturedArguments() {
|
func (c *KubeSettings_CurrentNamespaceName_OngoingVerification) GetAllCapturedArguments() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (verifier *VerifierKubeSettings) NamespaceNames() *KubeSettings_NamespaceNames_OngoingVerification {
|
func (verifier *VerifierKubeSettings) NamespaceNames(_param0 []v1.Namespace) *KubeSettings_NamespaceNames_OngoingVerification {
|
||||||
params := []pegomock.Param{}
|
params := []pegomock.Param{_param0}
|
||||||
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "NamespaceNames", params, verifier.timeout)
|
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "NamespaceNames", params, verifier.timeout)
|
||||||
return &KubeSettings_NamespaceNames_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
return &KubeSettings_NamespaceNames_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||||
}
|
}
|
||||||
|
|
@ -228,8 +225,18 @@ type KubeSettings_NamespaceNames_OngoingVerification struct {
|
||||||
methodInvocations []pegomock.MethodInvocation
|
methodInvocations []pegomock.MethodInvocation
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *KubeSettings_NamespaceNames_OngoingVerification) GetCapturedArguments() {
|
func (c *KubeSettings_NamespaceNames_OngoingVerification) GetCapturedArguments() []v1.Namespace {
|
||||||
|
_param0 := c.GetAllCapturedArguments()
|
||||||
|
return _param0[len(_param0)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *KubeSettings_NamespaceNames_OngoingVerification) GetAllCapturedArguments() {
|
func (c *KubeSettings_NamespaceNames_OngoingVerification) GetAllCapturedArguments() (_param0 [][]v1.Namespace) {
|
||||||
|
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
|
||||||
|
if len(params) > 0 {
|
||||||
|
_param0 = make([][]v1.Namespace, len(params[0]))
|
||||||
|
for u, param := range params[0] {
|
||||||
|
_param0[u] = param.([]v1.Namespace)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/derailed/k9s/internal/k8s"
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -28,13 +26,13 @@ func NewNamespace() *Namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate a namespace is setup correctly
|
// Validate a namespace is setup correctly
|
||||||
func (n *Namespace) Validate(c k8s.Connection, ks KubeSettings) {
|
func (n *Namespace) Validate(c Connection, ks KubeSettings) {
|
||||||
nns, err := c.DialOrDie().CoreV1().Namespaces().List(metav1.ListOptions{})
|
nns, err := c.ValidNamespaces()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
nn := ks.NamespaceNames(nns.Items)
|
nn := ks.NamespaceNames(nns)
|
||||||
if !n.isAllNamespace() && !InList(nn, n.Active) {
|
if !n.isAllNamespace() && !InList(nn, n.Active) {
|
||||||
log.Debug().Msg("[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
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package config_test
|
package config_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/derailed/k9s/internal/config"
|
"github.com/derailed/k9s/internal/config"
|
||||||
|
|
@ -10,43 +10,43 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNSValidate(t *testing.T) {
|
func TestNSValidate(t *testing.T) {
|
||||||
setup(t)
|
mc := NewMockConnection()
|
||||||
|
m.When(mc.ValidNamespaces()).ThenReturn(namespaces(), nil)
|
||||||
|
mk := NewMockKubeSettings()
|
||||||
|
m.When(mk.NamespaceNames(namespaces())).ThenReturn([]string{"ns1", "ns2", "default"})
|
||||||
|
|
||||||
ns := config.NewNamespace()
|
ns := config.NewNamespace()
|
||||||
|
ns.Validate(mc, mk)
|
||||||
|
|
||||||
ksMock := NewMockKubeSettings()
|
mk.VerifyWasCalledOnce()
|
||||||
m.When(ksMock.NamespaceNames()).ThenReturn([]string{"ns1", "ns2", "default"}, nil)
|
|
||||||
|
|
||||||
ns.Validate(ksMock)
|
|
||||||
ksMock.VerifyWasCalledOnce()
|
|
||||||
assert.Equal(t, "default", ns.Active)
|
assert.Equal(t, "default", ns.Active)
|
||||||
assert.Equal(t, []string{"default"}, ns.Favorites)
|
assert.Equal(t, []string{"default"}, ns.Favorites)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNSValidateMissing(t *testing.T) {
|
func TestNSValidateMissing(t *testing.T) {
|
||||||
setup(t)
|
mc := NewMockConnection()
|
||||||
|
m.When(mc.ValidNamespaces()).ThenReturn(namespaces(), nil)
|
||||||
|
mk := NewMockKubeSettings()
|
||||||
|
m.When(mk.NamespaceNames(namespaces())).ThenReturn([]string{"ns1", "ns2"})
|
||||||
|
|
||||||
ns := config.NewNamespace()
|
ns := config.NewNamespace()
|
||||||
|
ns.Validate(mc, mk)
|
||||||
|
|
||||||
ksMock := NewMockKubeSettings()
|
mk.VerifyWasCalledOnce()
|
||||||
m.When(ksMock.NamespaceNames()).ThenReturn([]string{"ns1", "ns2"}, nil)
|
|
||||||
ns.Validate(ksMock)
|
|
||||||
|
|
||||||
ksMock.VerifyWasCalledOnce()
|
|
||||||
assert.Equal(t, "default", ns.Active)
|
assert.Equal(t, "default", ns.Active)
|
||||||
assert.Equal(t, []string{}, ns.Favorites)
|
assert.Equal(t, []string{}, ns.Favorites)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNSValidateNoNS(t *testing.T) {
|
func TestNSValidateNoNS(t *testing.T) {
|
||||||
setup(t)
|
mc := NewMockConnection()
|
||||||
|
m.When(mc.ValidNamespaces()).ThenReturn(namespaces(), fmt.Errorf("Crap!"))
|
||||||
|
mk := NewMockKubeSettings()
|
||||||
|
m.When(mk.NamespaceNames(namespaces())).ThenReturn([]string{"ns1", "ns2"})
|
||||||
|
|
||||||
ns := config.NewNamespace()
|
ns := config.NewNamespace()
|
||||||
|
ns.Validate(mc, mk)
|
||||||
|
|
||||||
ksMock := NewMockKubeSettings()
|
mk.VerifyWasCalledOnce()
|
||||||
m.When(ksMock.NamespaceNames()).ThenReturn([]string{"ns1", "ns2"}, errors.New("boom"))
|
|
||||||
ns.Validate(ksMock)
|
|
||||||
|
|
||||||
ksMock.VerifyWasCalledOnce()
|
|
||||||
assert.Equal(t, "default", ns.Active)
|
assert.Equal(t, "default", ns.Active)
|
||||||
assert.Equal(t, []string{"default"}, ns.Favorites)
|
assert.Equal(t, []string{"default"}, ns.Favorites)
|
||||||
}
|
}
|
||||||
|
|
@ -64,12 +64,13 @@ func TestNSSetActive(t *testing.T) {
|
||||||
{"ns4", allNS},
|
{"ns4", allNS},
|
||||||
}
|
}
|
||||||
|
|
||||||
ksMock := NewMockKubeSettings()
|
mk := NewMockKubeSettings()
|
||||||
m.When(ksMock.NamespaceNames()).ThenReturn(allNS, nil)
|
m.When(mk.NamespaceNames(namespaces())).ThenReturn(allNS)
|
||||||
|
|
||||||
ns := config.NewNamespace()
|
ns := config.NewNamespace()
|
||||||
for _, u := range uu {
|
for _, u := range uu {
|
||||||
err := ns.SetActive(u.ns, ksMock)
|
err := ns.SetActive(u.ns, mk)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, u.ns, ns.Active)
|
assert.Equal(t, u.ns, ns.Active)
|
||||||
assert.Equal(t, u.fav, ns.Favorites)
|
assert.Equal(t, u.fav, ns.Favorites)
|
||||||
|
|
@ -79,12 +80,13 @@ func TestNSSetActive(t *testing.T) {
|
||||||
func TestNSValidateRmFavs(t *testing.T) {
|
func TestNSValidateRmFavs(t *testing.T) {
|
||||||
allNS := []string{"default", "kube-system"}
|
allNS := []string{"default", "kube-system"}
|
||||||
|
|
||||||
ksMock := NewMockKubeSettings()
|
mc := NewMockConnection()
|
||||||
m.When(ksMock.NamespaceNames()).ThenReturn(allNS, nil)
|
mk := NewMockKubeSettings()
|
||||||
|
m.When(mk.NamespaceNames(namespaces())).ThenReturn(allNS)
|
||||||
|
|
||||||
ns := config.NewNamespace()
|
ns := config.NewNamespace()
|
||||||
ns.Favorites = []string{"default", "fred", "blee"}
|
ns.Favorites = []string{"default", "fred", "blee"}
|
||||||
|
ns.Validate(mc, mk)
|
||||||
|
|
||||||
ns.Validate(ksMock)
|
assert.Equal(t, []string{"fred"}, ns.Favorites)
|
||||||
assert.Equal(t, []string{"default"}, ns.Favorites)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ package k8s
|
||||||
import (
|
import (
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/client-go/dynamic"
|
"k8s.io/client-go/dynamic"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
|
|
@ -47,6 +49,7 @@ type (
|
||||||
HasMetrics() bool
|
HasMetrics() bool
|
||||||
IsNamespaced(n string) bool
|
IsNamespaced(n string) bool
|
||||||
SupportsResource(group string) bool
|
SupportsResource(group string) bool
|
||||||
|
ValidNamespaces() ([]v1.Namespace, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// APIClient represents a Kubernetes api client.
|
// APIClient represents a Kubernetes api client.
|
||||||
|
|
@ -70,6 +73,16 @@ func InitConnectionOrDie(config *Config, logger zerolog.Logger) *APIClient {
|
||||||
return &conn
|
return &conn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidNamespaces returns a collection of valid namespaces.
|
||||||
|
// Bozo!! filter active?
|
||||||
|
func (a *APIClient) ValidNamespaces() ([]v1.Namespace, error) {
|
||||||
|
nn, err := a.DialOrDie().CoreV1().Namespaces().List(metav1.ListOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nn.Items, nil
|
||||||
|
}
|
||||||
|
|
||||||
// IsNamespaced check on server if given resource is namespaced
|
// IsNamespaced check on server if given resource is namespaced
|
||||||
func (a *APIClient) IsNamespaced(res string) bool {
|
func (a *APIClient) IsNamespaced(res string) bool {
|
||||||
list, _ := a.DialOrDie().Discovery().ServerPreferredResources()
|
list, _ := a.DialOrDie().Discovery().ServerPreferredResources()
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ package k8s
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Cluster represents a Kubernetes cluster.
|
// Cluster represents a Kubernetes cluster.
|
||||||
|
|
@ -55,3 +57,13 @@ func (c *Cluster) UserName() string {
|
||||||
}
|
}
|
||||||
return usr
|
return usr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FetchNodes get all available nodes in the cluster.
|
||||||
|
func (c *Cluster) FetchNodes() ([]v1.Node, error) {
|
||||||
|
list, err := c.DialOrDie().CoreV1().Nodes().List(metav1.ListOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return list.Items, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,17 +7,6 @@ import (
|
||||||
"k8s.io/client-go/tools/clientcmd/api"
|
"k8s.io/client-go/tools/clientcmd/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Switchable represents a switchable resource.
|
|
||||||
type Switchable interface {
|
|
||||||
Switch(ctx string) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// SwitchableResource represents a Kubernetes clusters configurations.
|
|
||||||
type SwitchableResource interface {
|
|
||||||
Cruder
|
|
||||||
Switchable
|
|
||||||
}
|
|
||||||
|
|
||||||
// NamedContext represents a named cluster context.
|
// NamedContext represents a named cluster context.
|
||||||
type NamedContext struct {
|
type NamedContext struct {
|
||||||
Name string
|
Name string
|
||||||
|
|
@ -39,6 +28,8 @@ func (c *NamedContext) MustCurrentContextName() string {
|
||||||
return cl
|
return cl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Context represents a Kubernetes Context.
|
// Context represents a Kubernetes Context.
|
||||||
type Context struct {
|
type Context struct {
|
||||||
Connection
|
Connection
|
||||||
|
|
@ -84,6 +75,15 @@ func (c *Context) Delete(_, n string) error {
|
||||||
return c.Config().DelContext(n)
|
return c.Config().DelContext(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MustCurrentContextName return the active context name.
|
||||||
|
func (c *Context) MustCurrentContextName() string {
|
||||||
|
cl, err := c.Config().CurrentContextName()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return cl
|
||||||
|
}
|
||||||
|
|
||||||
// Switch to another context.
|
// Switch to another context.
|
||||||
func (c *Context) Switch(ctx string) error {
|
func (c *Context) Switch(ctx string) error {
|
||||||
c.SwitchContextOrDie(ctx)
|
c.SwitchContextOrDie(ctx)
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,8 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
"k8s.io/cli-runtime/pkg/genericclioptions/printers"
|
"k8s.io/cli-runtime/pkg/genericclioptions/printers"
|
||||||
"k8s.io/client-go/dynamic"
|
|
||||||
"k8s.io/client-go/kubernetes"
|
|
||||||
restclient "k8s.io/client-go/rest"
|
|
||||||
"k8s.io/kubernetes/pkg/kubectl/describe"
|
"k8s.io/kubernetes/pkg/kubectl/describe"
|
||||||
versioned "k8s.io/kubernetes/pkg/kubectl/describe/versioned"
|
versioned "k8s.io/kubernetes/pkg/kubectl/describe/versioned"
|
||||||
v "k8s.io/metrics/pkg/client/clientset/versioned"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
|
@ -27,18 +23,7 @@ type (
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connection represents a Kubenetes apiserver connection.
|
// Connection represents a Kubenetes apiserver connection.
|
||||||
Connection interface {
|
Connection k8s.Connection
|
||||||
Config() *k8s.Config
|
|
||||||
DialOrDie() kubernetes.Interface
|
|
||||||
SwitchContextOrDie(ctx string)
|
|
||||||
NSDialOrDie() dynamic.NamespaceableResourceInterface
|
|
||||||
RestConfigOrDie() *restclient.Config
|
|
||||||
MXDial() (*v.Clientset, error)
|
|
||||||
DynDialOrDie() dynamic.Interface
|
|
||||||
HasMetrics() bool
|
|
||||||
IsNamespaced(n string) bool
|
|
||||||
SupportsResource(group string) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Factory creates new tabular resources.
|
// Factory creates new tabular resources.
|
||||||
Factory interface {
|
Factory interface {
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,16 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// SwitchableResource represents a resource that can be switched.
|
// Switchable represents a switchable resource.
|
||||||
SwitchableResource interface {
|
Switchable interface {
|
||||||
|
Switch(ctx string) error
|
||||||
|
MustCurrentContextName() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwitchableCruder represents a resource that can be switched.
|
||||||
|
SwitchableCruder interface {
|
||||||
Cruder
|
Cruder
|
||||||
k8s.Switchable
|
Switchable
|
||||||
}
|
}
|
||||||
|
|
||||||
// Context tracks a kubernetes resource.
|
// Context tracks a kubernetes resource.
|
||||||
|
|
@ -50,7 +56,7 @@ func (r *Context) New(i interface{}) Columnar {
|
||||||
|
|
||||||
// Switch out current context.
|
// Switch out current context.
|
||||||
func (r *Context) Switch(c string) error {
|
func (r *Context) Switch(c string) error {
|
||||||
return r.Resource.(SwitchableResource).Switch(c)
|
return r.Resource.(Switchable).Switch(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Marshal the resource to yaml.
|
// Marshal the resource to yaml.
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ func NewContextListWithArgs(ns string, ctx *resource.Context) resource.List {
|
||||||
return resource.NewList(resource.NotNamespaced, "ctx", ctx, resource.SwitchAccess)
|
return resource.NewList(resource.NotNamespaced, "ctx", ctx, resource.SwitchAccess)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewContextWithArgs(c k8s.Connection, s resource.SwitchableResource) *resource.Context {
|
func NewContextWithArgs(c k8s.Connection, s resource.SwitchableCruder) *resource.Context {
|
||||||
ctx := &resource.Context{Base: resource.NewBase(c, s)}
|
ctx := &resource.Context{Base: resource.NewBase(c, s)}
|
||||||
ctx.Factory = ctx
|
ctx.Factory = ctx
|
||||||
return ctx
|
return ctx
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ type ClusterRole struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClusterRoleList returns a new resource list.
|
// NewClusterRoleList returns a new resource list.
|
||||||
func NewClusterRoleList(c k8s.Connection, ns string) List {
|
func NewClusterRoleList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
NotNamespaced,
|
NotNamespaced,
|
||||||
"clusterrole",
|
"clusterrole",
|
||||||
|
|
@ -23,7 +23,7 @@ func NewClusterRoleList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClusterRole instantiates a new ClusterRole.
|
// NewClusterRole instantiates a new ClusterRole.
|
||||||
func NewClusterRole(c k8s.Connection) *ClusterRole {
|
func NewClusterRole(c Connection) *ClusterRole {
|
||||||
cr := &ClusterRole{&Base{Connection: c, Resource: k8s.NewClusterRole(c)}, nil}
|
cr := &ClusterRole{&Base{Connection: c, Resource: k8s.NewClusterRole(c)}, nil}
|
||||||
cr.Factory = cr
|
cr.Factory = cr
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ type ClusterRoleBinding struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClusterRoleBindingList returns a new resource list.
|
// NewClusterRoleBindingList returns a new resource list.
|
||||||
func NewClusterRoleBindingList(c k8s.Connection, _ string) List {
|
func NewClusterRoleBindingList(c Connection, _ string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
NotNamespaced,
|
NotNamespaced,
|
||||||
"clusterrolebinding",
|
"clusterrolebinding",
|
||||||
|
|
@ -23,7 +23,7 @@ func NewClusterRoleBindingList(c k8s.Connection, _ string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClusterRoleBinding instantiates a new ClusterRoleBinding.
|
// NewClusterRoleBinding instantiates a new ClusterRoleBinding.
|
||||||
func NewClusterRoleBinding(c k8s.Connection) *ClusterRoleBinding {
|
func NewClusterRoleBinding(c Connection) *ClusterRoleBinding {
|
||||||
crb := &ClusterRoleBinding{&Base{Connection: c, Resource: k8s.NewClusterRoleBinding(c)}, nil}
|
crb := &ClusterRoleBinding{&Base{Connection: c, Resource: k8s.NewClusterRoleBinding(c)}, nil}
|
||||||
crb.Factory = crb
|
crb.Factory = crb
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ type CRD struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCRDList returns a new resource list.
|
// NewCRDList returns a new resource list.
|
||||||
func NewCRDList(c k8s.Connection, ns string) List {
|
func NewCRDList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
NotNamespaced,
|
NotNamespaced,
|
||||||
"crd",
|
"crd",
|
||||||
|
|
@ -27,7 +27,7 @@ func NewCRDList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCRD instantiates a new CRD.
|
// NewCRD instantiates a new CRD.
|
||||||
func NewCRD(c k8s.Connection) *CRD {
|
func NewCRD(c Connection) *CRD {
|
||||||
crd := &CRD{&Base{Connection: c, Resource: k8s.NewCRD(c)}, nil}
|
crd := &CRD{&Base{Connection: c, Resource: k8s.NewCRD(c)}, nil}
|
||||||
crd.Factory = crd
|
crd.Factory = crd
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ type (
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewCronJobList returns a new resource list.
|
// NewCronJobList returns a new resource list.
|
||||||
func NewCronJobList(c k8s.Connection, ns string) List {
|
func NewCronJobList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
ns,
|
ns,
|
||||||
"cronjob",
|
"cronjob",
|
||||||
|
|
@ -38,7 +38,7 @@ func NewCronJobList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCronJob instantiates a new CronJob.
|
// NewCronJob instantiates a new CronJob.
|
||||||
func NewCronJob(c k8s.Connection) *CronJob {
|
func NewCronJob(c Connection) *CronJob {
|
||||||
cj := &CronJob{&Base{Connection: c, Resource: k8s.NewCronJob(c)}, nil}
|
cj := &CronJob{&Base{Connection: c, Resource: k8s.NewCronJob(c)}, nil}
|
||||||
cj.Factory = cj
|
cj.Factory = cj
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewCronJobListWithArgs(ns string, r *resource.CronJob) resource.List {
|
func NewCronJobListWithArgs(ns string, r *resource.CronJob) resource.List {
|
||||||
return resource.NewList(ns, "cronjob", r, resource.AllVerbsAccess|resource.DescribeAccess)
|
return resource.NewList(ns, "cj", r, resource.AllVerbsAccess|resource.DescribeAccess)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCronJobWithArgs(conn k8s.Connection, res resource.Cruder) *resource.CronJob {
|
func NewCronJobWithArgs(conn k8s.Connection, res resource.Cruder) *resource.CronJob {
|
||||||
|
|
@ -31,7 +31,7 @@ func TestCronJobListAccess(t *testing.T) {
|
||||||
l.SetNamespace(ns)
|
l.SetNamespace(ns)
|
||||||
|
|
||||||
assert.Equal(t, ns, l.GetNamespace())
|
assert.Equal(t, ns, l.GetNamespace())
|
||||||
assert.Equal(t, "cronjob", l.GetName())
|
assert.Equal(t, "cj", l.GetName())
|
||||||
for _, a := range []int{resource.GetAccess, resource.ListAccess, resource.DeleteAccess, resource.ViewAccess, resource.EditAccess} {
|
for _, a := range []int{resource.GetAccess, resource.ListAccess, resource.DeleteAccess, resource.ViewAccess, resource.EditAccess} {
|
||||||
assert.True(t, l.Access(a))
|
assert.True(t, l.Access(a))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ type Deployment struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDeploymentList returns a new resource list.
|
// NewDeploymentList returns a new resource list.
|
||||||
func NewDeploymentList(c k8s.Connection, ns string) List {
|
func NewDeploymentList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
ns,
|
ns,
|
||||||
"deploy",
|
"deploy",
|
||||||
|
|
@ -25,7 +25,7 @@ func NewDeploymentList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDeployment instantiates a new Deployment.
|
// NewDeployment instantiates a new Deployment.
|
||||||
func NewDeployment(c k8s.Connection) *Deployment {
|
func NewDeployment(c Connection) *Deployment {
|
||||||
d := &Deployment{&Base{Connection: c, Resource: k8s.NewDeployment(c)}, nil}
|
d := &Deployment{&Base{Connection: c, Resource: k8s.NewDeployment(c)}, nil}
|
||||||
d.Factory = d
|
d.Factory = d
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ type DaemonSet struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDaemonSetList returns a new resource list.
|
// NewDaemonSetList returns a new resource list.
|
||||||
func NewDaemonSetList(c k8s.Connection, ns string) List {
|
func NewDaemonSetList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
ns,
|
ns,
|
||||||
"ds",
|
"ds",
|
||||||
|
|
@ -25,7 +25,7 @@ func NewDaemonSetList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDaemonSet instantiates a new DaemonSet.
|
// NewDaemonSet instantiates a new DaemonSet.
|
||||||
func NewDaemonSet(c k8s.Connection) *DaemonSet {
|
func NewDaemonSet(c Connection) *DaemonSet {
|
||||||
ds := &DaemonSet{&Base{Connection: c, Resource: k8s.NewDaemonSet(c)}, nil}
|
ds := &DaemonSet{&Base{Connection: c, Resource: k8s.NewDaemonSet(c)}, nil}
|
||||||
ds.Factory = ds
|
ds.Factory = ds
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ type Endpoints struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEndpointsList returns a new resource list.
|
// NewEndpointsList returns a new resource list.
|
||||||
func NewEndpointsList(c k8s.Connection, ns string) List {
|
func NewEndpointsList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
ns,
|
ns,
|
||||||
"ep",
|
"ep",
|
||||||
|
|
@ -27,7 +27,7 @@ func NewEndpointsList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEndpoints instantiates a new Endpoints.
|
// NewEndpoints instantiates a new Endpoints.
|
||||||
func NewEndpoints(c k8s.Connection) *Endpoints {
|
func NewEndpoints(c Connection) *Endpoints {
|
||||||
ep := &Endpoints{&Base{Connection: c, Resource: k8s.NewEndpoints(c)}, nil}
|
ep := &Endpoints{&Base{Connection: c, Resource: k8s.NewEndpoints(c)}, nil}
|
||||||
ep.Factory = ep
|
ep.Factory = ep
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ type Event struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEventList returns a new resource list.
|
// NewEventList returns a new resource list.
|
||||||
func NewEventList(c k8s.Connection, ns string) List {
|
func NewEventList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
ns,
|
ns,
|
||||||
"ev",
|
"ev",
|
||||||
|
|
@ -26,7 +26,7 @@ func NewEventList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEvent instantiates a new Event.
|
// NewEvent instantiates a new Event.
|
||||||
func NewEvent(c k8s.Connection) *Event {
|
func NewEvent(c Connection) *Event {
|
||||||
ev := &Event{&Base{Connection: c, Resource: k8s.NewEvent(c)}, nil}
|
ev := &Event{&Base{Connection: c, Resource: k8s.NewEvent(c)}, nil}
|
||||||
ev.Factory = ev
|
ev.Factory = ev
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ type HPA struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHPAList returns a new resource list.
|
// NewHPAList returns a new resource list.
|
||||||
func NewHPAList(c k8s.Connection, ns string) List {
|
func NewHPAList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
ns,
|
ns,
|
||||||
"hpa",
|
"hpa",
|
||||||
|
|
@ -27,7 +27,7 @@ func NewHPAList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHPA instantiates a new HPA.
|
// NewHPA instantiates a new HPA.
|
||||||
func NewHPA(c k8s.Connection) *HPA {
|
func NewHPA(c Connection) *HPA {
|
||||||
hpa := &HPA{&Base{Connection: c, Resource: k8s.NewHPA(c)}, nil}
|
hpa := &HPA{&Base{Connection: c, Resource: k8s.NewHPA(c)}, nil}
|
||||||
hpa.Factory = hpa
|
hpa.Factory = hpa
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ type Ingress struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewIngressList returns a new resource list.
|
// NewIngressList returns a new resource list.
|
||||||
func NewIngressList(c k8s.Connection, ns string) List {
|
func NewIngressList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
ns,
|
ns,
|
||||||
"ing",
|
"ing",
|
||||||
|
|
@ -26,7 +26,7 @@ func NewIngressList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewIngress instantiates a new Ingress.
|
// NewIngress instantiates a new Ingress.
|
||||||
func NewIngress(c k8s.Connection) *Ingress {
|
func NewIngress(c Connection) *Ingress {
|
||||||
ing := &Ingress{&Base{Connection: c, Resource: k8s.NewIngress(c)}, nil}
|
ing := &Ingress{&Base{Connection: c, Resource: k8s.NewIngress(c)}, nil}
|
||||||
ing.Factory = ing
|
ing.Factory = ing
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,22 +4,24 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/derailed/k9s/internal/k8s"
|
"github.com/derailed/k9s/internal/k8s"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
v1 "k8s.io/api/batch/v1"
|
batchv1 "k8s.io/api/batch/v1"
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/duration"
|
"k8s.io/apimachinery/pkg/util/duration"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Job tracks a kubernetes resource.
|
// Job tracks a kubernetes resource.
|
||||||
type Job struct {
|
type Job struct {
|
||||||
*Base
|
*Base
|
||||||
instance *v1.Job
|
instance *batchv1.Job
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewJobList returns a new resource list.
|
// NewJobList returns a new resource list.
|
||||||
func NewJobList(c k8s.Connection, ns string) List {
|
func NewJobList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
ns,
|
ns,
|
||||||
"job",
|
"job",
|
||||||
|
|
@ -29,7 +31,7 @@ func NewJobList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewJob instantiates a new Job.
|
// NewJob instantiates a new Job.
|
||||||
func NewJob(c k8s.Connection) *Job {
|
func NewJob(c Connection) *Job {
|
||||||
j := &Job{&Base{Connection: c, Resource: k8s.NewJob(c)}, nil}
|
j := &Job{&Base{Connection: c, Resource: k8s.NewJob(c)}, nil}
|
||||||
j.Factory = j
|
j.Factory = j
|
||||||
|
|
||||||
|
|
@ -40,9 +42,9 @@ func NewJob(c k8s.Connection) *Job {
|
||||||
func (r *Job) New(i interface{}) Columnar {
|
func (r *Job) New(i interface{}) Columnar {
|
||||||
c := NewJob(r.Connection)
|
c := NewJob(r.Connection)
|
||||||
switch instance := i.(type) {
|
switch instance := i.(type) {
|
||||||
case *v1.Job:
|
case *batchv1.Job:
|
||||||
c.instance = instance
|
c.instance = instance
|
||||||
case v1.Job:
|
case batchv1.Job:
|
||||||
c.instance = &instance
|
c.instance = &instance
|
||||||
default:
|
default:
|
||||||
log.Fatal().Msgf("unknown Job type %#v", i)
|
log.Fatal().Msgf("unknown Job type %#v", i)
|
||||||
|
|
@ -60,7 +62,7 @@ func (r *Job) Marshal(path string) (string, error) {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
jo := i.(*v1.Job)
|
jo := i.(*batchv1.Job)
|
||||||
jo.TypeMeta.APIVersion = "extensions/v1beta1"
|
jo.TypeMeta.APIVersion = "extensions/v1beta1"
|
||||||
jo.TypeMeta.Kind = "Job"
|
jo.TypeMeta.Kind = "Job"
|
||||||
|
|
||||||
|
|
@ -121,7 +123,7 @@ func (*Job) Header(ns string) Row {
|
||||||
hh = append(hh, "NAMESPACE")
|
hh = append(hh, "NAMESPACE")
|
||||||
}
|
}
|
||||||
|
|
||||||
return append(hh, "NAME", "COMPLETIONS", "DURATION", "AGE")
|
return append(hh, "NAME", "COMPLETIONS", "DURATION", "CONTAINERS", "IMAGES", "AGE")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fields retrieves displayable fields.
|
// Fields retrieves displayable fields.
|
||||||
|
|
@ -133,10 +135,14 @@ func (r *Job) Fields(ns string) Row {
|
||||||
ff = append(ff, i.Namespace)
|
ff = append(ff, i.Namespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cc, ii := r.toContainers(i.Spec.Template.Spec)
|
||||||
|
|
||||||
return append(ff,
|
return append(ff,
|
||||||
i.Name,
|
i.Name,
|
||||||
r.toCompletion(i.Spec, i.Status),
|
r.toCompletion(i.Spec, i.Status),
|
||||||
r.toDuration(i.Status),
|
r.toDuration(i.Status),
|
||||||
|
cc,
|
||||||
|
ii,
|
||||||
toAge(i.ObjectMeta.CreationTimestamp),
|
toAge(i.ObjectMeta.CreationTimestamp),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -144,7 +150,30 @@ func (r *Job) Fields(ns string) Row {
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Helpers...
|
// Helpers...
|
||||||
|
|
||||||
func (*Job) toCompletion(spec v1.JobSpec, status v1.JobStatus) (s string) {
|
func (*Job) toContainers(p v1.PodSpec) (string, string) {
|
||||||
|
cc := make([]string, 0, len(p.InitContainers)+len(p.Containers))
|
||||||
|
ii := make([]string, 0, len(cc))
|
||||||
|
for _, c := range p.InitContainers {
|
||||||
|
cc = append(cc, c.Name)
|
||||||
|
ii = append(ii, c.Image)
|
||||||
|
}
|
||||||
|
for _, c := range p.Containers {
|
||||||
|
cc = append(cc, c.Name)
|
||||||
|
ii = append(ii, c.Image)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limit to 2 of each...
|
||||||
|
if len(cc) > 2 {
|
||||||
|
cc = append(cc[:2], "...")
|
||||||
|
}
|
||||||
|
if len(ii) > 2 {
|
||||||
|
ii = append(ii[:2], "...")
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(cc, ","), strings.Join(ii, ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Job) toCompletion(spec batchv1.JobSpec, status batchv1.JobStatus) (s string) {
|
||||||
if spec.Completions != nil {
|
if spec.Completions != nil {
|
||||||
return fmt.Sprintf("%d/%d", status.Succeeded, *spec.Completions)
|
return fmt.Sprintf("%d/%d", status.Succeeded, *spec.Completions)
|
||||||
}
|
}
|
||||||
|
|
@ -159,7 +188,7 @@ func (*Job) toCompletion(spec v1.JobSpec, status v1.JobStatus) (s string) {
|
||||||
return fmt.Sprintf("%d/1", status.Succeeded)
|
return fmt.Sprintf("%d/1", status.Succeeded)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Job) toDuration(status v1.JobStatus) string {
|
func (*Job) toDuration(status batchv1.JobStatus) string {
|
||||||
switch {
|
switch {
|
||||||
case status.StartTime == nil:
|
case status.StartTime == nil:
|
||||||
case status.CompletionTime == nil:
|
case status.CompletionTime == nil:
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ func TestJobListData(t *testing.T) {
|
||||||
assert.Equal(t, 1, len(td.Rows))
|
assert.Equal(t, 1, len(td.Rows))
|
||||||
assert.Equal(t, "blee", l.GetNamespace())
|
assert.Equal(t, "blee", l.GetNamespace())
|
||||||
row := td.Rows["blee/fred"]
|
row := td.Rows["blee/fred"]
|
||||||
assert.Equal(t, 4, len(row.Deltas))
|
assert.Equal(t, 6, len(row.Deltas))
|
||||||
for _, d := range row.Deltas {
|
for _, d := range row.Deltas {
|
||||||
assert.Equal(t, "", d)
|
assert.Equal(t, "", d)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -234,6 +234,25 @@ func (mock *MockClusterMeta) UserName() string {
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mock *MockClusterMeta) ValidNamespaces() ([]v1.Namespace, error) {
|
||||||
|
if mock == nil {
|
||||||
|
panic("mock must not be nil. Use myMock := NewMockClusterMeta().")
|
||||||
|
}
|
||||||
|
params := []pegomock.Param{}
|
||||||
|
result := pegomock.GetGenericMockFrom(mock).Invoke("ValidNamespaces", params, []reflect.Type{reflect.TypeOf((*[]v1.Namespace)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
|
||||||
|
var ret0 []v1.Namespace
|
||||||
|
var ret1 error
|
||||||
|
if len(result) != 0 {
|
||||||
|
if result[0] != nil {
|
||||||
|
ret0 = result[0].([]v1.Namespace)
|
||||||
|
}
|
||||||
|
if result[1] != nil {
|
||||||
|
ret1 = result[1].(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
func (mock *MockClusterMeta) Version() (string, error) {
|
func (mock *MockClusterMeta) Version() (string, error) {
|
||||||
if mock == nil {
|
if mock == nil {
|
||||||
panic("mock must not be nil. Use myMock := NewMockClusterMeta().")
|
panic("mock must not be nil. Use myMock := NewMockClusterMeta().")
|
||||||
|
|
@ -558,6 +577,23 @@ func (c *ClusterMeta_UserName_OngoingVerification) GetCapturedArguments() {
|
||||||
func (c *ClusterMeta_UserName_OngoingVerification) GetAllCapturedArguments() {
|
func (c *ClusterMeta_UserName_OngoingVerification) GetAllCapturedArguments() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (verifier *VerifierClusterMeta) ValidNamespaces() *ClusterMeta_ValidNamespaces_OngoingVerification {
|
||||||
|
params := []pegomock.Param{}
|
||||||
|
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "ValidNamespaces", params, verifier.timeout)
|
||||||
|
return &ClusterMeta_ValidNamespaces_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ClusterMeta_ValidNamespaces_OngoingVerification struct {
|
||||||
|
mock *MockClusterMeta
|
||||||
|
methodInvocations []pegomock.MethodInvocation
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ClusterMeta_ValidNamespaces_OngoingVerification) GetCapturedArguments() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ClusterMeta_ValidNamespaces_OngoingVerification) GetAllCapturedArguments() {
|
||||||
|
}
|
||||||
|
|
||||||
func (verifier *VerifierClusterMeta) Version() *ClusterMeta_Version_OngoingVerification {
|
func (verifier *VerifierClusterMeta) Version() *ClusterMeta_Version_OngoingVerification {
|
||||||
params := []pegomock.Param{}
|
params := []pegomock.Param{}
|
||||||
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Version", params, verifier.timeout)
|
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Version", params, verifier.timeout)
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ package resource_test
|
||||||
import (
|
import (
|
||||||
k8s "github.com/derailed/k9s/internal/k8s"
|
k8s "github.com/derailed/k9s/internal/k8s"
|
||||||
pegomock "github.com/petergtz/pegomock"
|
pegomock "github.com/petergtz/pegomock"
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
dynamic "k8s.io/client-go/dynamic"
|
dynamic "k8s.io/client-go/dynamic"
|
||||||
kubernetes "k8s.io/client-go/kubernetes"
|
kubernetes "k8s.io/client-go/kubernetes"
|
||||||
rest "k8s.io/client-go/rest"
|
rest "k8s.io/client-go/rest"
|
||||||
|
|
@ -169,6 +170,25 @@ func (mock *MockConnection) SwitchContextOrDie(_param0 string) {
|
||||||
pegomock.GetGenericMockFrom(mock).Invoke("SwitchContextOrDie", params, []reflect.Type{})
|
pegomock.GetGenericMockFrom(mock).Invoke("SwitchContextOrDie", params, []reflect.Type{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mock *MockConnection) ValidNamespaces() ([]v1.Namespace, error) {
|
||||||
|
if mock == nil {
|
||||||
|
panic("mock must not be nil. Use myMock := NewMockConnection().")
|
||||||
|
}
|
||||||
|
params := []pegomock.Param{}
|
||||||
|
result := pegomock.GetGenericMockFrom(mock).Invoke("ValidNamespaces", params, []reflect.Type{reflect.TypeOf((*[]v1.Namespace)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
|
||||||
|
var ret0 []v1.Namespace
|
||||||
|
var ret1 error
|
||||||
|
if len(result) != 0 {
|
||||||
|
if result[0] != nil {
|
||||||
|
ret0 = result[0].([]v1.Namespace)
|
||||||
|
}
|
||||||
|
if result[1] != nil {
|
||||||
|
ret1 = result[1].(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
func (mock *MockConnection) VerifyWasCalledOnce() *VerifierConnection {
|
func (mock *MockConnection) VerifyWasCalledOnce() *VerifierConnection {
|
||||||
return &VerifierConnection{
|
return &VerifierConnection{
|
||||||
mock: mock,
|
mock: mock,
|
||||||
|
|
@ -405,3 +425,20 @@ func (c *Connection_SwitchContextOrDie_OngoingVerification) GetAllCapturedArgume
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (verifier *VerifierConnection) ValidNamespaces() *Connection_ValidNamespaces_OngoingVerification {
|
||||||
|
params := []pegomock.Param{}
|
||||||
|
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "ValidNamespaces", params, verifier.timeout)
|
||||||
|
return &Connection_ValidNamespaces_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Connection_ValidNamespaces_OngoingVerification struct {
|
||||||
|
mock *MockConnection
|
||||||
|
methodInvocations []pegomock.MethodInvocation
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_ValidNamespaces_OngoingVerification) GetCapturedArguments() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection_ValidNamespaces_OngoingVerification) GetAllCapturedArguments() {
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ type Node struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNodeList returns a new resource list.
|
// NewNodeList returns a new resource list.
|
||||||
func NewNodeList(c k8s.Connection, mx MetricsServer, ns string) List {
|
func NewNodeList(c Connection, mx MetricsServer, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
NotNamespaced,
|
NotNamespaced,
|
||||||
"no",
|
"no",
|
||||||
|
|
@ -34,7 +34,7 @@ func NewNodeList(c k8s.Connection, mx MetricsServer, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNode instantiates a new Node.
|
// NewNode instantiates a new Node.
|
||||||
func NewNode(c k8s.Connection, mx MetricsServer) *Node {
|
func NewNode(c Connection, mx MetricsServer) *Node {
|
||||||
n := &Node{&Base{Connection: c, Resource: k8s.NewNode(c)}, nil, mx, k8s.NodeMetrics{}}
|
n := &Node{&Base{Connection: c, Resource: k8s.NewNode(c)}, nil, mx, k8s.NodeMetrics{}}
|
||||||
n.Factory = n
|
n.Factory = n
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ type Namespace struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNamespaceList returns a new resource list.
|
// NewNamespaceList returns a new resource list.
|
||||||
func NewNamespaceList(c k8s.Connection, ns string) List {
|
func NewNamespaceList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
NotNamespaced,
|
NotNamespaced,
|
||||||
"ns",
|
"ns",
|
||||||
|
|
@ -23,7 +23,7 @@ func NewNamespaceList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNamespace instantiates a new Namespace.
|
// NewNamespace instantiates a new Namespace.
|
||||||
func NewNamespace(c k8s.Connection) *Namespace {
|
func NewNamespace(c Connection) *Namespace {
|
||||||
n := &Namespace{&Base{Connection: c, Resource: k8s.NewNamespace(c)}, nil}
|
n := &Namespace{&Base{Connection: c, Resource: k8s.NewNamespace(c)}, nil}
|
||||||
n.Factory = n
|
n.Factory = n
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ type PodDisruptionBudget struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPDBList returns a new resource list.
|
// NewPDBList returns a new resource list.
|
||||||
func NewPDBList(c k8s.Connection, ns string) List {
|
func NewPDBList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
ns,
|
ns,
|
||||||
"pdb",
|
"pdb",
|
||||||
|
|
@ -26,7 +26,7 @@ func NewPDBList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPDB instantiates a new PDB.
|
// NewPDB instantiates a new PDB.
|
||||||
func NewPDB(c k8s.Connection) *PodDisruptionBudget {
|
func NewPDB(c Connection) *PodDisruptionBudget {
|
||||||
p := &PodDisruptionBudget{&Base{Connection: c, Resource: k8s.NewPodDisruptionBudget(c)}, nil}
|
p := &PodDisruptionBudget{&Base{Connection: c, Resource: k8s.NewPodDisruptionBudget(c)}, nil}
|
||||||
p.Factory = p
|
p.Factory = p
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ type (
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewPodList returns a new resource list.
|
// NewPodList returns a new resource list.
|
||||||
func NewPodList(c k8s.Connection, mx MetricsServer, ns string) List {
|
func NewPodList(c Connection, mx MetricsServer, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
ns,
|
ns,
|
||||||
"po",
|
"po",
|
||||||
|
|
@ -54,7 +54,7 @@ func NewPodList(c k8s.Connection, mx MetricsServer, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPod instantiates a new Pod.
|
// NewPod instantiates a new Pod.
|
||||||
func NewPod(c k8s.Connection, mx MetricsServer) *Pod {
|
func NewPod(c Connection, mx MetricsServer) *Pod {
|
||||||
p := &Pod{&Base{Connection: c, Resource: k8s.NewPod(c)}, nil, mx, k8s.PodMetrics{}}
|
p := &Pod{&Base{Connection: c, Resource: k8s.NewPod(c)}, nil, mx, k8s.PodMetrics{}}
|
||||||
p.Factory = p
|
p.Factory = p
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ type PV struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPVList returns a new resource list.
|
// NewPVList returns a new resource list.
|
||||||
func NewPVList(c k8s.Connection, ns string) List {
|
func NewPVList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
NotNamespaced,
|
NotNamespaced,
|
||||||
"pv",
|
"pv",
|
||||||
|
|
@ -26,7 +26,7 @@ func NewPVList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPV instantiates a new PV.
|
// NewPV instantiates a new PV.
|
||||||
func NewPV(c k8s.Connection) *PV {
|
func NewPV(c Connection) *PV {
|
||||||
p := &PV{&Base{Connection: c, Resource: k8s.NewPV(c)}, nil}
|
p := &PV{&Base{Connection: c, Resource: k8s.NewPV(c)}, nil}
|
||||||
p.Factory = p
|
p.Factory = p
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ type PVC struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPVCList returns a new resource list.
|
// NewPVCList returns a new resource list.
|
||||||
func NewPVCList(c k8s.Connection, ns string) List {
|
func NewPVCList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
ns,
|
ns,
|
||||||
"pvc",
|
"pvc",
|
||||||
|
|
@ -23,7 +23,7 @@ func NewPVCList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPVC instantiates a new PVC.
|
// NewPVC instantiates a new PVC.
|
||||||
func NewPVC(c k8s.Connection) *PVC {
|
func NewPVC(c Connection) *PVC {
|
||||||
p := &PVC{&Base{Connection: c, Resource: k8s.NewPVC(c)}, nil}
|
p := &PVC{&Base{Connection: c, Resource: k8s.NewPVC(c)}, nil}
|
||||||
p.Factory = p
|
p.Factory = p
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ type ReplicationController struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewReplicationControllerList returns a new resource list.
|
// NewReplicationControllerList returns a new resource list.
|
||||||
func NewReplicationControllerList(c k8s.Connection, ns string) List {
|
func NewReplicationControllerList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
ns,
|
ns,
|
||||||
"rc",
|
"rc",
|
||||||
|
|
@ -25,7 +25,7 @@ func NewReplicationControllerList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewReplicationController instantiates a new ReplicationController.
|
// NewReplicationController instantiates a new ReplicationController.
|
||||||
func NewReplicationController(c k8s.Connection) *ReplicationController {
|
func NewReplicationController(c Connection) *ReplicationController {
|
||||||
r := &ReplicationController{&Base{Connection: c, Resource: k8s.NewReplicationController(c)}, nil}
|
r := &ReplicationController{&Base{Connection: c, Resource: k8s.NewReplicationController(c)}, nil}
|
||||||
r.Factory = r
|
r.Factory = r
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ type Role struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRoleList returns a new resource list.
|
// NewRoleList returns a new resource list.
|
||||||
func NewRoleList(c k8s.Connection, ns string) List {
|
func NewRoleList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
ns,
|
ns,
|
||||||
"role",
|
"role",
|
||||||
|
|
@ -25,7 +25,7 @@ func NewRoleList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRole instantiates a new Role.
|
// NewRole instantiates a new Role.
|
||||||
func NewRole(c k8s.Connection) *Role {
|
func NewRole(c Connection) *Role {
|
||||||
r := &Role{&Base{Connection: c, Resource: k8s.NewRole(c)}, nil}
|
r := &Role{&Base{Connection: c, Resource: k8s.NewRole(c)}, nil}
|
||||||
r.Factory = r
|
r.Factory = r
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ type RoleBinding struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRoleBindingList returns a new resource list.
|
// NewRoleBindingList returns a new resource list.
|
||||||
func NewRoleBindingList(c k8s.Connection, ns string) List {
|
func NewRoleBindingList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
ns,
|
ns,
|
||||||
"rolebinding",
|
"rolebinding",
|
||||||
|
|
@ -25,7 +25,7 @@ func NewRoleBindingList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRoleBinding instantiates a new RoleBinding.
|
// NewRoleBinding instantiates a new RoleBinding.
|
||||||
func NewRoleBinding(c k8s.Connection) *RoleBinding {
|
func NewRoleBinding(c Connection) *RoleBinding {
|
||||||
r := &RoleBinding{&Base{Connection: c, Resource: k8s.NewRoleBinding(c)}, nil}
|
r := &RoleBinding{&Base{Connection: c, Resource: k8s.NewRoleBinding(c)}, nil}
|
||||||
r.Factory = r
|
r.Factory = r
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ type ReplicaSet struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewReplicaSetList returns a new resource list.
|
// NewReplicaSetList returns a new resource list.
|
||||||
func NewReplicaSetList(c k8s.Connection, ns string) List {
|
func NewReplicaSetList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
ns,
|
ns,
|
||||||
"rs",
|
"rs",
|
||||||
|
|
@ -25,7 +25,7 @@ func NewReplicaSetList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewReplicaSet instantiates a new ReplicaSet.
|
// NewReplicaSet instantiates a new ReplicaSet.
|
||||||
func NewReplicaSet(c k8s.Connection) *ReplicaSet {
|
func NewReplicaSet(c Connection) *ReplicaSet {
|
||||||
r := &ReplicaSet{&Base{Connection: c, Resource: k8s.NewReplicaSet(c)}, nil}
|
r := &ReplicaSet{&Base{Connection: c, Resource: k8s.NewReplicaSet(c)}, nil}
|
||||||
r.Factory = r
|
r.Factory = r
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ type ServiceAccount struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServiceAccountList returns a new resource list.
|
// NewServiceAccountList returns a new resource list.
|
||||||
func NewServiceAccountList(c k8s.Connection, ns string) List {
|
func NewServiceAccountList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
ns,
|
ns,
|
||||||
"sa",
|
"sa",
|
||||||
|
|
@ -25,7 +25,7 @@ func NewServiceAccountList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServiceAccount instantiates a new ServiceAccount.
|
// NewServiceAccount instantiates a new ServiceAccount.
|
||||||
func NewServiceAccount(c k8s.Connection) *ServiceAccount {
|
func NewServiceAccount(c Connection) *ServiceAccount {
|
||||||
s := &ServiceAccount{&Base{Connection: c, Resource: k8s.NewServiceAccount(c)}, nil}
|
s := &ServiceAccount{&Base{Connection: c, Resource: k8s.NewServiceAccount(c)}, nil}
|
||||||
s.Factory = s
|
s.Factory = s
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ type Secret struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSecretList returns a new resource list.
|
// NewSecretList returns a new resource list.
|
||||||
func NewSecretList(c k8s.Connection, ns string) List {
|
func NewSecretList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
ns,
|
ns,
|
||||||
"secret",
|
"secret",
|
||||||
|
|
@ -25,7 +25,7 @@ func NewSecretList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSecret instantiates a new Secret.
|
// NewSecret instantiates a new Secret.
|
||||||
func NewSecret(c k8s.Connection) *Secret {
|
func NewSecret(c Connection) *Secret {
|
||||||
s := &Secret{&Base{Connection: c, Resource: k8s.NewSecret(c)}, nil}
|
s := &Secret{&Base{Connection: c, Resource: k8s.NewSecret(c)}, nil}
|
||||||
s.Factory = s
|
s.Factory = s
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ type StatefulSet struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStatefulSetList returns a new resource list.
|
// NewStatefulSetList returns a new resource list.
|
||||||
func NewStatefulSetList(c k8s.Connection, ns string) List {
|
func NewStatefulSetList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
ns,
|
ns,
|
||||||
"sts",
|
"sts",
|
||||||
|
|
@ -25,7 +25,7 @@ func NewStatefulSetList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStatefulSet instantiates a new StatefulSet.
|
// NewStatefulSet instantiates a new StatefulSet.
|
||||||
func NewStatefulSet(c k8s.Connection) *StatefulSet {
|
func NewStatefulSet(c Connection) *StatefulSet {
|
||||||
s := &StatefulSet{&Base{Connection: c, Resource: k8s.NewStatefulSet(c)}, nil}
|
s := &StatefulSet{&Base{Connection: c, Resource: k8s.NewStatefulSet(c)}, nil}
|
||||||
s.Factory = s
|
s.Factory = s
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ type Service struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServiceList returns a new resource list.
|
// NewServiceList returns a new resource list.
|
||||||
func NewServiceList(c k8s.Connection, ns string) List {
|
func NewServiceList(c Connection, ns string) List {
|
||||||
return NewList(
|
return NewList(
|
||||||
ns,
|
ns,
|
||||||
"svc",
|
"svc",
|
||||||
|
|
@ -29,7 +29,7 @@ func NewServiceList(c k8s.Connection, ns string) List {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewService instantiates a new Service.
|
// NewService instantiates a new Service.
|
||||||
func NewService(c k8s.Connection) *Service {
|
func NewService(c Connection) *Service {
|
||||||
s := &Service{&Base{Connection: c, Resource: k8s.NewService(c)}, nil}
|
s := &Service{&Base{Connection: c, Resource: k8s.NewService(c)}, nil}
|
||||||
s.Factory = s
|
s.Factory = s
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -128,12 +128,6 @@ func (a *appView) conn() k8s.Connection {
|
||||||
|
|
||||||
// Run starts the application loop
|
// Run starts the application loop
|
||||||
func (a *appView) Run() {
|
func (a *appView) Run() {
|
||||||
defer func() {
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
log.Error().Msgf("%#v", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
<-time.After(splashTime * time.Second)
|
<-time.After(splashTime * time.Second)
|
||||||
a.showPage("main")
|
a.showPage("main")
|
||||||
|
|
@ -302,9 +296,9 @@ func logoView() tview.Primitive {
|
||||||
v.SetWordWrap(false)
|
v.SetWordWrap(false)
|
||||||
v.SetWrap(false)
|
v.SetWrap(false)
|
||||||
v.SetDynamicColors(true)
|
v.SetDynamicColors(true)
|
||||||
for i, s := range logoSmall {
|
for i, s := range LogoSmall {
|
||||||
fmt.Fprintf(v, "[orange::b]%s", s)
|
fmt.Fprintf(v, "[orange::b]%s", s)
|
||||||
if i+1 < len(logoSmall) {
|
if i+1 < len(LogoSmall) {
|
||||||
fmt.Fprintf(v, "\n")
|
fmt.Fprintf(v, "\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package views
|
package views
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/derailed/k9s/internal/k8s"
|
||||||
"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"
|
||||||
|
|
@ -18,7 +19,7 @@ func newInfoView(app *appView) *clusterInfoView {
|
||||||
return &clusterInfoView{
|
return &clusterInfoView{
|
||||||
app: app,
|
app: app,
|
||||||
Table: tview.NewTable(),
|
Table: tview.NewTable(),
|
||||||
cluster: resource.NewCluster(app.conn(), &log.Logger),
|
cluster: resource.NewCluster(app.conn(), &log.Logger, k8s.NewMetricsServer(app.conn())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,12 +80,12 @@ func (v *clusterInfoView) refresh() {
|
||||||
v.GetCell(row, 1).SetText(v.cluster.Version())
|
v.GetCell(row, 1).SetText(v.cluster.Version())
|
||||||
row++
|
row++
|
||||||
|
|
||||||
nodes, err := v.cluster.GetNodes()
|
nodes, err := v.cluster.FetchNodes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn().Msgf("ClusterInfo %s", err)
|
log.Warn().Msgf("ClusterInfo %s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
mxNodes, err := v.cluster.GetNodesMetrics()
|
mxNodes, err := v.cluster.FetchNodesMetrics()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn().Msgf("ClusterInfo %s", err)
|
log.Warn().Msgf("ClusterInfo %s", err)
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package views
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/derailed/k9s/internal/k8s"
|
||||||
"github.com/derailed/k9s/internal/resource"
|
"github.com/derailed/k9s/internal/resource"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
@ -53,8 +54,15 @@ func (c *command) run(cmd string) bool {
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
if res, ok := resourceViews()[cmd]; ok {
|
if res, ok := resourceViews()[cmd]; ok {
|
||||||
v = res.viewFn(res.title, c.app, res.listFn(c.app.conn(), resource.DefaultNamespace), res.colorerFn)
|
var r resource.List
|
||||||
|
if res.listMxFn != nil {
|
||||||
|
r = res.listMxFn(c.app.conn(), k8s.NewMetricsServer(c.app.conn()), resource.DefaultNamespace)
|
||||||
|
} else {
|
||||||
|
r = res.listFn(c.app.conn(), resource.DefaultNamespace)
|
||||||
|
}
|
||||||
|
v = res.viewFn(res.title, c.app, r, res.colorerFn)
|
||||||
c.app.flash(flashInfo, fmt.Sprintf("Viewing %s in namespace %s...", res.title, c.app.config.ActiveNamespace()))
|
c.app.flash(flashInfo, fmt.Sprintf("Viewing %s in namespace %s...", res.title, c.app.config.ActiveNamespace()))
|
||||||
|
log.Debug().Msgf("Running command %s", cmd)
|
||||||
c.exec(cmd, v)
|
c.exec(cmd, v)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,8 @@ import (
|
||||||
|
|
||||||
type (
|
type (
|
||||||
viewFn func(ns string, app *appView, list resource.List, colorer colorerFn) resourceViewer
|
viewFn func(ns string, app *appView, list resource.List, colorer colorerFn) resourceViewer
|
||||||
listFn func(c k8s.Connection, ns string) resource.List
|
listFn func(c resource.Connection, ns string) resource.List
|
||||||
|
listMxFn func(c resource.Connection, mx resource.MetricsServer, ns string) resource.List
|
||||||
colorerFn func(ns string, evt *resource.RowEvent) tcell.Color
|
colorerFn func(ns string, evt *resource.RowEvent) tcell.Color
|
||||||
|
|
||||||
resCmd struct {
|
resCmd struct {
|
||||||
|
|
@ -16,6 +17,7 @@ type (
|
||||||
api string
|
api string
|
||||||
viewFn viewFn
|
viewFn viewFn
|
||||||
listFn listFn
|
listFn listFn
|
||||||
|
listMxFn listMxFn
|
||||||
colorerFn colorerFn
|
colorerFn colorerFn
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -100,7 +102,7 @@ func resourceViews() map[string]resCmd {
|
||||||
listFn: resource.NewCRDList,
|
listFn: resource.NewCRDList,
|
||||||
colorerFn: defaultColorer,
|
colorerFn: defaultColorer,
|
||||||
},
|
},
|
||||||
"cron": {
|
"cj": {
|
||||||
title: "CronJobs",
|
title: "CronJobs",
|
||||||
api: "batch",
|
api: "batch",
|
||||||
viewFn: newCronJobView,
|
viewFn: newCronJobView,
|
||||||
|
|
@ -156,7 +158,7 @@ func resourceViews() map[string]resCmd {
|
||||||
listFn: resource.NewIngressList,
|
listFn: resource.NewIngressList,
|
||||||
colorerFn: defaultColorer,
|
colorerFn: defaultColorer,
|
||||||
},
|
},
|
||||||
"job": {
|
"jo": {
|
||||||
title: "Jobs",
|
title: "Jobs",
|
||||||
api: "batch",
|
api: "batch",
|
||||||
viewFn: newJobView,
|
viewFn: newJobView,
|
||||||
|
|
@ -167,7 +169,7 @@ func resourceViews() map[string]resCmd {
|
||||||
title: "Nodes",
|
title: "Nodes",
|
||||||
api: "",
|
api: "",
|
||||||
viewFn: newNodeView,
|
viewFn: newNodeView,
|
||||||
listFn: resource.NewNodeList,
|
listMxFn: resource.NewNodeList,
|
||||||
colorerFn: nsColorer,
|
colorerFn: nsColorer,
|
||||||
},
|
},
|
||||||
"ns": {
|
"ns": {
|
||||||
|
|
@ -188,7 +190,7 @@ func resourceViews() map[string]resCmd {
|
||||||
title: "Pods",
|
title: "Pods",
|
||||||
api: "",
|
api: "",
|
||||||
viewFn: newPodView,
|
viewFn: newPodView,
|
||||||
listFn: resource.NewPodList,
|
listMxFn: resource.NewPodList,
|
||||||
colorerFn: podColorer,
|
colorerFn: podColorer,
|
||||||
},
|
},
|
||||||
"pv": {
|
"pv": {
|
||||||
|
|
|
||||||
|
|
@ -80,19 +80,17 @@ func (v *resourceView) init(ctx context.Context, ns string) {
|
||||||
v.selectedItem, v.selectedNS = noSelection, ns
|
v.selectedItem, v.selectedNS = noSelection, ns
|
||||||
|
|
||||||
go func(ctx context.Context) {
|
go func(ctx context.Context) {
|
||||||
initTick := refreshDelay
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
log.Debug().Msgf("%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(v.app.config.K9s.RefreshRate) * time.Second):
|
||||||
v.refresh()
|
v.refresh()
|
||||||
initTick = float64(v.app.config.K9s.RefreshRate)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}(ctx)
|
}(ctx)
|
||||||
v.refreshActions()
|
v.refresh()
|
||||||
if tv, ok := v.CurrentPage().Item.(*tableView); ok {
|
if tv, ok := v.CurrentPage().Item.(*tableView); ok {
|
||||||
tv.Select(0, 0)
|
tv.Select(0, 0)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ const (
|
||||||
product = "Kubernetes CLI Island Style!"
|
product = "Kubernetes CLI Island Style!"
|
||||||
)
|
)
|
||||||
|
|
||||||
var logoSmall = []string{
|
var LogoSmall = []string{
|
||||||
` ____ __.________ `,
|
` ____ __.________ `,
|
||||||
`| |/ _/ __ \______`,
|
`| |/ _/ __ \______`,
|
||||||
`| < \____ / ___/`,
|
`| < \____ / ___/`,
|
||||||
|
|
@ -22,7 +22,7 @@ var logoSmall = []string{
|
||||||
` \/ \/ `,
|
` \/ \/ `,
|
||||||
}
|
}
|
||||||
|
|
||||||
var logo = []string{
|
var Logo = []string{
|
||||||
` ____ __.________ _________ .____ .___ `,
|
` ____ __.________ _________ .____ .___ `,
|
||||||
`| |/ _/ __ \_____\_ ___ \| | | |`,
|
`| |/ _/ __ \_____\_ ___ \| | | |`,
|
||||||
`| < \____ / ___/ \ \/| | | |`,
|
`| < \____ / ___/ \ \/| | | |`,
|
||||||
|
|
@ -63,7 +63,7 @@ func newSplash(rev string) *splashView {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *splashView) layoutLogo(t *tview.TextView) {
|
func (v *splashView) layoutLogo(t *tview.TextView) {
|
||||||
logo := strings.Join(logo, "\n[orange::b]")
|
logo := strings.Join(Logo, "\n[orange::b]")
|
||||||
fmt.Fprintf(t, "%s[orange::b]%s\n", strings.Repeat("\n", 2), logo)
|
fmt.Fprintf(t, "%s[orange::b]%s\n", strings.Repeat("\n", 2), logo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue