diff --git a/change_logs/release_v0.19.8.md b/change_logs/release_v0.19.8.md deleted file mode 100644 index 072a25ad..00000000 --- a/change_logs/release_v0.19.8.md +++ /dev/null @@ -1,57 +0,0 @@ - - -# Release v0.19.8 - -## Notes - -Thank you to all that contributed with flushing out issues and enhancements for K9s! I'll try to mark some of these issues as fixed. But if you don't mind grab the latest rev and see if we're happier with some of the fixes! If you've filed an issue please help me verify and close. Your support, kindness and awesome suggestions to make K9s better is as ever very much noticed and appreciated! - -Also if you dig this tool, consider joining our [sponsorhip program](https://github.com/sponsors/derailed) and/or make some noise on social! [@kitesurfer](https://twitter.com/kitesurfer) - -On Slack? Please join us [K9slackers](https://join.slack.com/t/k9sers/shared_invite/enQtOTA5MDEyNzI5MTU0LWQ1ZGI3MzliYzZhZWEyNzYxYzA3NjE0YTk1YmFmNzViZjIyNzhkZGI0MmJjYzhlNjdlMGJhYzE2ZGU1NjkyNTM) - ---- - -## Music Behind This Release - -And now for something a `beat` different... -I figured, why not share one of the tunes I was spinning when powering thru teh bugs. -I've just discovered this Turkish band and thought perhaps you can listen when reading this release notes? - -[Ruh - She Past Away](https://www.youtube.com/watch?v=B7f-opGKOyI) - -NOTE! Mind you I grew up with the `The Cure`, so likely not for everyone here 🙀 -NOTE! If you dig this please lmk and will make this a k9s release tradition... - -## PortForward revisited - -While performing port-forwards it could be convenient to use a different IP address on a per cluster basis. For this reason, we are introducing a configuration setting that allows you to set the host IP address for the port-forward dialog on a given cluster. The address currently defaults to `localhost`. - -Big Thanks and all credits goes to [Stowe4077](https://github.com/Stowe4077) and that very cute dog for raising this issue in the first place!! - -In order to change the configuration, edit your k9s config file as follows: - -```yaml -k9s: - ... - clusters: - blee: - namespace: - active: "" - favorites: - - fred - - default - view: - active: po - portForwardAddress: 1.2.3.4 -``` - -## Resolved Bugs/Features/PRs - -* [Issue #734](https://github.com/derailed/k9s/issues/734) -* [Issue #733](https://github.com/derailed/k9s/issues/733) -* [Issue #716](https://github.com/derailed/k9s/issues/716) - ---- - - © 2020 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0) diff --git a/change_logs/release_v0.20.0.md b/change_logs/release_v0.20.0.md new file mode 100644 index 00000000..510a6a51 --- /dev/null +++ b/change_logs/release_v0.20.0.md @@ -0,0 +1,69 @@ + + +# Release v0.20.0 + +## Notes + +Thank you to all that contributed with flushing out issues and enhancements for K9s! I'll try to mark some of these issues as fixed. But if you don't mind grab the latest rev and see if we're happier with some of the fixes! If you've filed an issue please help me verify and close. Your support, kindness and awesome suggestions to make K9s better is as ever very much noticed and appreciated! + +Also if you dig this tool, consider joining our [sponsorhip program](https://github.com/sponsors/derailed) and/or make some noise on social! [@kitesurfer](https://twitter.com/kitesurfer) + +On Slack? Please join us [K9slackers](https://join.slack.com/t/k9sers/shared_invite/enQtOTA5MDEyNzI5MTU0LWQ1ZGI3MzliYzZhZWEyNzYxYzA3NjE0YTk1YmFmNzViZjIyNzhkZGI0MmJjYzhlNjdlMGJhYzE2ZGU1NjkyNTM) + +--- + +## ♫ The Sound Behind The Release ♭ + +And now for something a `beat` different? + +I figured, why not share one of the tunes I was spinning when powering thru teh bugs? Might as well share the pain/pleasure roaght? + +I've just discovered this Turkish band, that I dig and figured I'll share it with you while you read these release notes... + +[Ruh - She Past Away](https://www.youtube.com/watch?v=B7f-opGKOyI) + +NOTE! Mind you I grew up on the `The Cure`, so likely not for everyone here 🙀 + +## PortForward Revisited + +While performing port-forwards, it could be convenient to specify a given IP address vs 'localhost' +for the forwarding host. For this reason, we are introducing a configuration setting that allows you to set the host IP address for the port-forward dialog on a per cluster basis. The IP address currently defaults to `localhost`. + +Big Thanks and all credits goes to [Stowe4077](https://github.com/Stowe4077) (and that very cute dog!) for raising this issue in the first place!! + +In order to change the configuration, edit your k9s config file as follows: + +```yaml +k9s: + ... + clusters: + blee: + namespace: + active: "" + favorites: + - fred + - default + view: + active: po + portForwardAddress: 1.2.3.4 +``` + +## And We've Got A Floater! + +I've been noodling on this feature for a while and thought it might be time to `float` this over to you guys... While operating on a cluster you may ask yourself: "Hum... wonder which resources use configmap `fred`?" Sure a quick grep through your manifests on disk will do fine, but what about the resources actually deployed on your cluster? Well my friends wonder no m'o, K9s knows! +While navigating to your ConfigMap View a new option will appear `UsedBy` pressing `u` will reveal any resources that are currently referencing that ConfigMap. As of this drop, this feature will be available for the usual suspects namely: ConfigMaps, Secrets and ServiceAccounts. K9s scans managing resources and locate references from Env vars, Volumes or ServiceAccounts. + +NOTE: This feature is expensive to produce and might take a while to fully resolve on larger clusters! Also K9s referential scans might not be full proof and the paint is still fresh on this one so trade carefully! More resources refs checks will be enabled once we've rinse and repeat on this deal. We hope you'll find this feature useful, if so, please make some noise! + +NOTE: There has been quick a bit of surgery on this drop, so this drop could be a bit unstable. Please watch out for that carp overbite! As always, Thank You All for your understanding, support and patience!! + +## Resolved Bugs/Features/PRs + +- [Issue #734](https://github.com/derailed/k9s/issues/734) +- [Issue #733](https://github.com/derailed/k9s/issues/733) +- [Issue #716](https://github.com/derailed/k9s/issues/716) +- [Issue #693](https://github.com/derailed/k9s/issues/693) + +--- + + © 2020 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0) diff --git a/cmd/root.go b/cmd/root.go index 420aa137..271618e5 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -78,23 +78,26 @@ func run(cmd *cobra.Command, args []string) { }() zerolog.SetGlobalLevel(parseLevel(*k9sFlags.LogLevel)) - cfg := loadConfiguration() + cfg, err := loadConfiguration() + if err != nil { + panic(err) + } app := view.NewApp(cfg) { defer app.BailOut() if err := app.Init(version, *k9sFlags.RefreshRate); err != nil { - panic(err) + panic(fmt.Sprintf("app init failed -- %v", err)) } if err := app.Run(); err != nil { - panic(err) + panic(fmt.Sprintf("app run failed %v", err)) } if view.ExitStatus != "" { - panic(view.ExitStatus) + panic(fmt.Sprintf("view exit status %s", view.ExitStatus)) } } } -func loadConfiguration() *config.Config { +func loadConfiguration() (*config.Config, error) { log.Info().Msg("🐶 K9s starting up...") // Load K9s config file... @@ -129,20 +132,25 @@ func loadConfiguration() *config.Config { } if err := k9sCfg.Refine(k8sFlags); err != nil { - log.Panic().Err(err) + log.Error().Err(err).Msgf("refine failed") + return nil, err } - k9sCfg.SetConnection(client.InitConnectionOrDie(k8sCfg)) + conn, err := client.InitConnection(k8sCfg) + if err != nil { + log.Error().Err(err).Msgf("failed to connect to cluster") + } else { + // Try to access server version if that fail. Connectivity issue? + if !k9sCfg.GetConnection().CheckConnectivity() { + log.Panic().Msgf("K9s can't connect to cluster") + } + log.Info().Msg("✅ Kubernetes connectivity") + if err := k9sCfg.Save(); err != nil { + log.Error().Err(err).Msg("Config save") + } + } + k9sCfg.SetConnection(conn) - // Try to access server version if that fail. Connectivity issue? - if !k9sCfg.GetConnection().CheckConnectivity() { - log.Panic().Msgf("K9s can't connect to cluster") - } - log.Info().Msg("✅ Kubernetes connectivity") - if err := k9sCfg.Save(); err != nil { - log.Error().Err(err).Msg("Config save") - } - - return k9sCfg + return k9sCfg, nil } func isBoolSet(b *bool) bool { diff --git a/go.mod b/go.mod index cde6a541..8551c34c 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.13 require ( 9fans.net/go v0.0.2 github.com/atotto/clipboard v0.1.2 - github.com/derailed/popeye v0.8.3 + github.com/derailed/popeye v0.8.4 github.com/derailed/tview v0.3.10 github.com/drone/envsubst v1.0.2 // indirect github.com/fatih/color v1.9.0 diff --git a/go.sum b/go.sum index 54056a66..ca7d1461 100644 --- a/go.sum +++ b/go.sum @@ -144,6 +144,8 @@ github.com/derailed/popeye v0.8.2 h1:O4JcIC3MwJS9pNKb8ZHLUJKoLPZW0gfcMqFoSYYdbAs github.com/derailed/popeye v0.8.2/go.mod h1:i4ge2tKHDKXgUq3NzFlIhVIBNHS0zFDMJWXsC2bVe2A= github.com/derailed/popeye v0.8.3 h1:fsZ+EfFlOzgQCAeerJuajJmSrLZTNEGyLI4LfEdUHJ8= github.com/derailed/popeye v0.8.3/go.mod h1:i4ge2tKHDKXgUq3NzFlIhVIBNHS0zFDMJWXsC2bVe2A= +github.com/derailed/popeye v0.8.4 h1:cvsPYPbrLmFhKfhfH1NtzS46rWsrxRSgX4EhIKLnlGQ= +github.com/derailed/popeye v0.8.4/go.mod h1:+u3tvVxADQQ2o6iJjgAO8cnQFq/GIWEUPXEWa1N6l54= github.com/derailed/tview v0.3.10 h1:n+iQwYh9Ff9STdR5hBhp+rTJRlu59q2xP2pHvwQbYPw= github.com/derailed/tview v0.3.10/go.mod h1:GJ3k/TIzEE+sj1L09/usk6HrkjsdadSsb03eHgPbcII= github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= diff --git a/internal/client/client.go b/internal/client/client.go index 3c36fd9c..ba26876d 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -2,6 +2,7 @@ package client import ( "context" + "errors" "fmt" "path/filepath" "strings" @@ -27,7 +28,7 @@ const ( cacheExpiry = 5 * time.Minute cacheMXKey = "metrics" cacheMXAPIKey = "metricsAPI" - checkConnTimeout = 10 * time.Second + checkConnTimeout = 5 * time.Second // CallTimeout represents default api call timeout. CallTimeout = 5 * time.Second @@ -56,15 +57,23 @@ func NewTestClient() *APIClient { } } -// InitConnectionOrDie initialize connection from command line args. +// InitConnection initialize connection from command line args. // Checks for connectivity with the api server. -func InitConnectionOrDie(config *Config) *APIClient { +func InitConnection(config *Config) (*APIClient, error) { a := APIClient{ config: config, cache: cache.NewLRUExpireCache(cacheSize), } - _ = a.supportsMetricsResources() - return &a + _, err := a.supportsMetricsResources() + if err == nil { + a.connOK = true + } + + return &a, err +} + +func (a *APIClient) ConnectionOK() bool { + return a.connOK } func makeSAR(ns, gvr string) *authorizationv1.SelfSubjectAccessReview { @@ -124,7 +133,10 @@ func (a *APIClient) clearCache() { // CanI checks if user has access to a certain resource. func (a *APIClient) CanI(ns, gvr string, verbs []string) (auth bool, err error) { - // log.Debug().Msgf("Check Access %q::%q", ns, gvr) + log.Debug().Msgf("Check Access %q::%q", ns, gvr) + if !a.connOK { + return false, errors.New("no API server connection") + } if IsClusterWide(ns) { ns = AllNamespaces } @@ -134,13 +146,18 @@ func (a *APIClient) CanI(ns, gvr string, verbs []string) (auth bool, err error) return auth, nil } } - dial, sar := a.DialOrDie().AuthorizationV1().SelfSubjectAccessReviews(), makeSAR(ns, gvr) + + dial, err := a.Dial() + if err != nil { + return false, err + } + client, sar := dial.AuthorizationV1().SelfSubjectAccessReviews(), makeSAR(ns, gvr) ctx, cancel := context.WithTimeout(context.Background(), CallTimeout) defer cancel() for _, v := range verbs { sar.Spec.ResourceAttributes.Verb = v - resp, err := dial.Create(ctx, sar, metav1.CreateOptions{}) + resp, err := client.Create(ctx, sar, metav1.CreateOptions{}) if err != nil { log.Warn().Err(err).Msgf(" Dial Failed!") a.cache.Add(key, false, cacheExpiry) @@ -164,7 +181,11 @@ func (a *APIClient) CurrentNamespaceName() (string, error) { // ServerVersion returns the current server version info. func (a *APIClient) ServerVersion() (*version.Info, error) { - return a.CachedDiscoveryOrDie().ServerVersion() + dial, err := a.CachedDiscovery() + if err != nil { + return nil, err + } + return dial.ServerVersion() } // ValidNamespaces returns all available namespaces. @@ -174,9 +195,13 @@ func (a *APIClient) ValidNamespaces() ([]v1.Namespace, error) { return nss, nil } } + dial, err := a.Dial() + if err != nil { + return nil, err + } ctx, cancel := context.WithTimeout(context.Background(), CallTimeout) defer cancel() - nn, err := a.DialOrDie().CoreV1().Namespaces().List(ctx, metav1.ListOptions{}) + nn, err := dial.CoreV1().Namespaces().List(ctx, metav1.ListOptions{}) if err != nil { return nil, err } @@ -197,18 +222,20 @@ func (a *APIClient) CheckConnectivity() (status bool) { a.connOK = status }() - cfg, err := a.config.flags.ToRESTConfig() + // Need to reload to pickup any kubeconfig changes. + config := NewConfig(a.config.flags) + cfg, err := config.RESTConfig() if err != nil { - return + return false } - cfg.Timeout = checkConnTimeout - client, err := kubernetes.NewForConfig(cfg) if err != nil { log.Error().Err(err).Msgf("Unable to connect to api server") return } + log.Debug().Msgf("Checking APIServer on %#v", cfg.Host) + // Check connection if _, err := client.ServerVersion(); err == nil { if !a.connOK { log.Debug().Msgf("RESETING CON!!") @@ -229,7 +256,8 @@ func (a *APIClient) Config() *Config { // HasMetrics returns true if the cluster supports metrics. func (a *APIClient) HasMetrics() bool { - if !a.supportsMetricsResources() { + ok, err := a.supportsMetricsResources() + if !ok || err != nil { return false } v, ok := a.cache.Get(cacheMXKey) @@ -256,61 +284,76 @@ func (a *APIClient) HasMetrics() bool { return flag } -// DialOrDie returns a handle to api server or die. -func (a *APIClient) DialOrDie() kubernetes.Interface { +// Dial returns a handle to api server or die. +func (a *APIClient) Dial() (kubernetes.Interface, error) { + if !a.connOK { + return nil, errors.New("No connection to dial") + } if a.client != nil { - return a.client + return a.client, nil } - var err error - if a.client, err = kubernetes.NewForConfig(a.RestConfigOrDie()); err != nil { - log.Panic().Err(err).Msgf("Unable to connect to api server") + cfg, err := a.RestConfig() + if err != nil { + return nil, err + } + if a.client, err = kubernetes.NewForConfig(cfg); err != nil { + return nil, err } - return a.client + return a.client, nil } // RestConfigOrDie returns a rest api client. -func (a *APIClient) RestConfigOrDie() *restclient.Config { +func (a *APIClient) RestConfig() (*restclient.Config, error) { cfg, err := a.config.RESTConfig() if err != nil { - log.Panic().Err(err).Msgf("Unable to connect to api server") + return nil, err } - return cfg + return cfg, nil } -// CachedDiscoveryOrDie returns a cached discovery client. -func (a *APIClient) CachedDiscoveryOrDie() *disk.CachedDiscoveryClient { +// CachedDiscovery returns a cached discovery client. +func (a *APIClient) CachedDiscovery() (*disk.CachedDiscoveryClient, error) { + if !a.connOK { + return nil, errors.New("No connection to cached dial") + } a.mx.Lock() defer a.mx.Unlock() if a.cachedClient != nil { - return a.cachedClient + return a.cachedClient, nil } - rc := a.RestConfigOrDie() - httpCacheDir := filepath.Join(mustHomeDir(), ".kube", "http-cache") - discCacheDir := filepath.Join(mustHomeDir(), ".kube", "cache", "discovery", toHostDir(rc.Host)) - - var err error - a.cachedClient, err = disk.NewCachedDiscoveryClientForConfig(rc, discCacheDir, httpCacheDir, 10*time.Minute) + cfg, err := a.RestConfig() if err != nil { - log.Panic().Msgf("Unable to connect to discovery client %v", err) + return nil, err } - return a.cachedClient + httpCacheDir := filepath.Join(mustHomeDir(), ".kube", "http-cache") + discCacheDir := filepath.Join(mustHomeDir(), ".kube", "cache", "discovery", toHostDir(cfg.Host)) + + a.cachedClient, err = disk.NewCachedDiscoveryClientForConfig(cfg, discCacheDir, httpCacheDir, cacheExpiry) + if err != nil { + return nil, err + } + return a.cachedClient, nil } -// DynDialOrDie returns a handle to a dynamic interface. -func (a *APIClient) DynDialOrDie() dynamic.Interface { +// DynDial returns a handle to a dynamic interface. +func (a *APIClient) DynDial() (dynamic.Interface, error) { if a.dClient != nil { - return a.dClient + return a.dClient, nil } - var err error - if a.dClient, err = dynamic.NewForConfig(a.RestConfigOrDie()); err != nil { + cfg, err := a.RestConfig() + if err != nil { + return nil, err + } + if a.dClient, err = dynamic.NewForConfig(cfg); err != nil { log.Panic().Err(err) } - return a.dClient + + return a.dClient, nil } // MXDial returns a handle to the metrics server. @@ -321,8 +364,13 @@ func (a *APIClient) MXDial() (*versioned.Clientset, error) { if a.mxsClient != nil { return a.mxsClient, nil } - var err error - if a.mxsClient, err = versioned.NewForConfig(a.RestConfigOrDie()); err != nil { + + cfg, err := a.RestConfig() + if err != nil { + return nil, err + } + + if a.mxsClient, err = versioned.NewForConfig(cfg); err != nil { log.Error().Err(err) } @@ -330,21 +378,27 @@ func (a *APIClient) MXDial() (*versioned.Clientset, error) { } // SwitchContext handles kubeconfig context switches. -func (a *APIClient) SwitchContext(ctx string) error { +func (a *APIClient) SwitchContext(name string) error { + log.Debug().Msgf("Switching context %q", name) currentCtx, err := a.config.CurrentContextName() if err != nil { return err } - if currentCtx == ctx { + if currentCtx == name { return nil } - if err := a.config.SwitchContext(ctx); err != nil { - return err + if e := a.config.SwitchContext(name); e != nil { + return e } a.clearCache() a.reset() - _ = a.supportsMetricsResources() + a.connOK = true + _, err = a.supportsMetricsResources() + if err != nil { + a.connOK = false + return err + } ResetMetrics() return nil @@ -360,7 +414,7 @@ func (a *APIClient) reset() { a.cachedClient = nil } -func (a *APIClient) supportsMetricsResources() (supported bool) { +func (a *APIClient) supportsMetricsResources() (supported bool, err error) { defer func() { a.cache.Add(cacheMXAPIKey, supported, cacheExpiry) }() @@ -374,7 +428,11 @@ func (a *APIClient) supportsMetricsResources() (supported bool) { return } - apiGroups, err := a.CachedDiscoveryOrDie().ServerGroups() + dial, err := a.CachedDiscovery() + if err != nil { + return false, err + } + apiGroups, err := dial.ServerGroups() if err != nil { log.Debug().Msgf("Unable to access servergroups %#v", err) return diff --git a/internal/client/config.go b/internal/client/config.go index cdea393c..3dd5fdbd 100644 --- a/internal/client/config.go +++ b/internal/client/config.go @@ -21,12 +21,11 @@ const ( // Config tracks a kubernetes configuration. type Config struct { - flags *genericclioptions.ConfigFlags - clientConfig clientcmd.ClientConfig - currentContext string - rawConfig *clientcmdapi.Config - restConfig *restclient.Config - mutex *sync.RWMutex + flags *genericclioptions.ConfigFlags + clientConfig clientcmd.ClientConfig + rawConfig *clientcmdapi.Config + restConfig *restclient.Config + mutex *sync.RWMutex } // NewConfig returns a new k8s config or an error if the flags are invalid. @@ -44,19 +43,16 @@ func (c *Config) Flags() *genericclioptions.ConfigFlags { // SwitchContext changes the kubeconfig context to a new cluster. func (c *Config) SwitchContext(name string) error { - currentCtx, err := c.CurrentContextName() - if err != nil { - return err + if c.flags.Context != nil && *c.flags.Context == name { + return nil } if _, err := c.GetContext(name); err != nil { return fmt.Errorf("context %s does not exist", name) } + c.reset() + c.flags.Context = &name - if currentCtx != name { - c.reset() - c.flags.Context, c.currentContext = &name, name - } return nil } @@ -276,15 +272,6 @@ func (c *Config) RawConfig() (clientcmdapi.Config, error) { c.mutex.Lock() defer c.mutex.Unlock() - if c.rawConfig != nil { - if c.rawConfig.CurrentContext == c.currentContext { - return *c.rawConfig, nil - } - log.Debug().Msgf("Context switch detected... %s vs %s", c.rawConfig.CurrentContext, c.currentContext) - c.currentContext = c.rawConfig.CurrentContext - c.reset() - } - if c.rawConfig == nil { c.ensureConfig() cfg, err := c.clientConfig.RawConfig() @@ -292,7 +279,9 @@ func (c *Config) RawConfig() (clientcmdapi.Config, error) { return cfg, err } c.rawConfig = &cfg - c.currentContext = cfg.CurrentContext + if c.flags.Context == nil { + c.flags.Context = &c.rawConfig.CurrentContext + } } return *c.rawConfig, nil @@ -310,6 +299,7 @@ func (c *Config) RESTConfig() (*restclient.Config, error) { } c.restConfig.QPS = defaultQPS c.restConfig.Burst = defaultBurst + c.restConfig.Timeout = checkConnTimeout log.Debug().Msgf("Connecting to API Server %s", c.restConfig.Host) return c.restConfig, nil diff --git a/internal/client/types.go b/internal/client/types.go index 61f1ef56..149fa836 100644 --- a/internal/client/types.go +++ b/internal/client/types.go @@ -72,23 +72,26 @@ type Connection interface { // Config returns current config. Config() *Config + // ConnectionOK checks api server connection status. + ConnectionOK() bool + // DialOrDie connects to api server. - DialOrDie() kubernetes.Interface + Dial() (kubernetes.Interface, error) // SwitchContext switches cluster based on context. SwitchContext(ctx string) error - // CachedDiscoveryOrDie connects to discovery client. - CachedDiscoveryOrDie() *disk.CachedDiscoveryClient + // CachedDiscovery connects to discovery client. + CachedDiscovery() (*disk.CachedDiscoveryClient, error) - // RestConfigOrDie connects to rest client. - RestConfigOrDie() *restclient.Config + // RestConfig connects to rest client. + RestConfig() (*restclient.Config, error) // MXDial connects to metrics server. MXDial() (*versioned.Clientset, error) - // DynDialOrDie connects to dynamic client. - DynDialOrDie() dynamic.Interface + // DynDial connects to dynamic client. + DynDial() (dynamic.Interface, error) // HasMetrics checks if metrics server is available. HasMetrics() bool diff --git a/internal/config/mock_connection_test.go b/internal/config/mock_connection_test.go index 3635f62a..fa7c641d 100644 --- a/internal/config/mock_connection_test.go +++ b/internal/config/mock_connection_test.go @@ -4,9 +4,6 @@ package config_test import ( - "reflect" - "time" - client "github.com/derailed/k9s/internal/client" pegomock "github.com/petergtz/pegomock" v1 "k8s.io/api/core/v1" @@ -16,6 +13,8 @@ import ( 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 { @@ -33,115 +32,6 @@ func NewMockConnection(options ...pegomock.Option) *MockConnection { func (mock *MockConnection) SetFailHandler(fh pegomock.FailHandler) { mock.fail = fh } func (mock *MockConnection) FailHandler() pegomock.FailHandler { return mock.fail } -func (mock *MockConnection) CachedDiscoveryOrDie() *disk.CachedDiscoveryClient { - if mock == nil { - panic("mock must not be nil. Use myMock := NewMockConnection().") - } - params := []pegomock.Param{} - result := pegomock.GetGenericMockFrom(mock).Invoke("CachedDiscoveryOrDie", params, []reflect.Type{reflect.TypeOf((**disk.CachedDiscoveryClient)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}) - var ret0 *disk.CachedDiscoveryClient - if len(result) != 0 { - if result[0] != nil { - ret0 = result[0].(*disk.CachedDiscoveryClient) - } - } - return ret0 -} - -func (mock *MockConnection) CanI(_param0 string, _param1 string, _param2 []string) (bool, error) { - if mock == nil { - panic("mock must not be nil. Use myMock := NewMockConnection().") - } - params := []pegomock.Param{_param0, _param1, _param2} - result := pegomock.GetGenericMockFrom(mock).Invoke("CanI", params, []reflect.Type{reflect.TypeOf((*bool)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}) - var ret0 bool - var ret1 error - if len(result) != 0 { - if result[0] != nil { - ret0 = result[0].(bool) - } - if result[1] != nil { - ret1 = result[1].(error) - } - } - return ret0, ret1 -} - -func (mock *MockConnection) Config() *client.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((**client.Config)(nil)).Elem()}) - var ret0 *client.Config - if len(result) != 0 { - if result[0] != nil { - ret0 = result[0].(*client.Config) - } - } - return ret0 -} - -func (mock *MockConnection) CheckConnectivity() bool { - if mock == nil { - panic("mock must not be nil. Use myMock := NewMockConnection().") - } - params := []pegomock.Param{} - result := pegomock.GetGenericMockFrom(mock).Invoke("CheckConnectivity", 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) 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) ActiveCluster() string { if mock == nil { panic("mock must not be nil. Use myMock := NewMockConnection().") @@ -172,12 +62,50 @@ func (mock *MockConnection) ActiveNamespace() string { return ret0 } -func (mock *MockConnection) IsActiveNamespace(s string) bool { +func (mock *MockConnection) CachedDiscovery() (*disk.CachedDiscoveryClient, error) { if mock == nil { panic("mock must not be nil. Use myMock := NewMockConnection().") } params := []pegomock.Param{} - result := pegomock.GetGenericMockFrom(mock).Invoke("IsActiveNamespace", params, []reflect.Type{reflect.TypeOf((*bool)(nil)).Elem()}) + result := pegomock.GetGenericMockFrom(mock).Invoke("CachedDiscovery", params, []reflect.Type{reflect.TypeOf((**disk.CachedDiscoveryClient)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}) + var ret0 *disk.CachedDiscoveryClient + var ret1 error + if len(result) != 0 { + if result[0] != nil { + ret0 = result[0].(*disk.CachedDiscoveryClient) + } + if result[1] != nil { + ret1 = result[1].(error) + } + } + return ret0, ret1 +} + +func (mock *MockConnection) CanI(_param0 string, _param1 string, _param2 []string) (bool, error) { + if mock == nil { + panic("mock must not be nil. Use myMock := NewMockConnection().") + } + params := []pegomock.Param{_param0, _param1, _param2} + result := pegomock.GetGenericMockFrom(mock).Invoke("CanI", params, []reflect.Type{reflect.TypeOf((*bool)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}) + var ret0 bool + var ret1 error + if len(result) != 0 { + if result[0] != nil { + ret0 = result[0].(bool) + } + if result[1] != nil { + ret1 = result[1].(error) + } + } + return ret0, ret1 +} + +func (mock *MockConnection) CheckConnectivity() bool { + if mock == nil { + panic("mock must not be nil. Use myMock := NewMockConnection().") + } + params := []pegomock.Param{} + result := pegomock.GetGenericMockFrom(mock).Invoke("CheckConnectivity", params, []reflect.Type{reflect.TypeOf((*bool)(nil)).Elem()}) var ret0 bool if len(result) != 0 { if result[0] != nil { @@ -187,12 +115,95 @@ func (mock *MockConnection) IsActiveNamespace(s string) bool { return ret0 } -func (mock *MockConnection) IsNamespaced(_param0 string) bool { +func (mock *MockConnection) Config() *client.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((**client.Config)(nil)).Elem()}) + var ret0 *client.Config + if len(result) != 0 { + if result[0] != nil { + ret0 = result[0].(*client.Config) + } + } + return ret0 +} + +func (mock *MockConnection) ConnectionOK() bool { + if mock == nil { + panic("mock must not be nil. Use myMock := NewMockConnection().") + } + params := []pegomock.Param{} + result := pegomock.GetGenericMockFrom(mock).Invoke("ConnectionOK", 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) Dial() (kubernetes.Interface, error) { + if mock == nil { + panic("mock must not be nil. Use myMock := NewMockConnection().") + } + params := []pegomock.Param{} + result := pegomock.GetGenericMockFrom(mock).Invoke("Dial", params, []reflect.Type{reflect.TypeOf((*kubernetes.Interface)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}) + var ret0 kubernetes.Interface + var ret1 error + if len(result) != 0 { + if result[0] != nil { + ret0 = result[0].(kubernetes.Interface) + } + if result[1] != nil { + ret1 = result[1].(error) + } + } + return ret0, ret1 +} + +func (mock *MockConnection) DynDial() (dynamic.Interface, error) { + if mock == nil { + panic("mock must not be nil. Use myMock := NewMockConnection().") + } + params := []pegomock.Param{} + result := pegomock.GetGenericMockFrom(mock).Invoke("DynDial", params, []reflect.Type{reflect.TypeOf((*dynamic.Interface)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}) + var ret0 dynamic.Interface + var ret1 error + if len(result) != 0 { + if result[0] != nil { + ret0 = result[0].(dynamic.Interface) + } + if result[1] != nil { + ret1 = result[1].(error) + } + } + return ret0, ret1 +} + +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) IsActiveNamespace(_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()}) + result := pegomock.GetGenericMockFrom(mock).Invoke("IsActiveNamespace", params, []reflect.Type{reflect.TypeOf((*bool)(nil)).Elem()}) var ret0 bool if len(result) != 0 { if result[0] != nil { @@ -221,17 +232,17 @@ func (mock *MockConnection) MXDial() (*versioned.Clientset, error) { return ret0, ret1 } -func (mock *MockConnection) NodePods(_param0 string) (*v1.PodList, error) { +func (mock *MockConnection) RestConfig() (*rest.Config, error) { if mock == nil { panic("mock must not be nil. Use myMock := NewMockConnection().") } - params := []pegomock.Param{_param0} - result := pegomock.GetGenericMockFrom(mock).Invoke("NodePods", params, []reflect.Type{reflect.TypeOf((**v1.PodList)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}) - var ret0 *v1.PodList + params := []pegomock.Param{} + result := pegomock.GetGenericMockFrom(mock).Invoke("RestConfig", params, []reflect.Type{reflect.TypeOf((**rest.Config)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}) + var ret0 *rest.Config var ret1 error if len(result) != 0 { if result[0] != nil { - ret0 = result[0].(*v1.PodList) + ret0 = result[0].(*rest.Config) } if result[1] != nil { ret1 = result[1].(error) @@ -240,21 +251,6 @@ func (mock *MockConnection) NodePods(_param0 string) (*v1.PodList, error) { return ret0, ret1 } -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) ServerVersion() (*version.Info, error) { if mock == nil { panic("mock must not be nil. Use myMock := NewMockConnection().") @@ -274,52 +270,19 @@ func (mock *MockConnection) ServerVersion() (*version.Info, error) { return ret0, ret1 } -func (mock *MockConnection) SupportsRes(_param0 string, _param1 []string) (string, bool, error) { - if mock == nil { - panic("mock must not be nil. Use myMock := NewMockConnection().") - } - params := []pegomock.Param{_param0, _param1} - result := pegomock.GetGenericMockFrom(mock).Invoke("SupportsRes", params, []reflect.Type{reflect.TypeOf((*string)(nil)).Elem(), reflect.TypeOf((*bool)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}) - var ret0 string - var ret1 bool - var ret2 error - if len(result) != 0 { - if result[0] != nil { - ret0 = result[0].(string) - } - if result[1] != nil { - ret1 = result[1].(bool) - } - if result[2] != nil { - ret2 = result[2].(error) - } - } - return ret0, ret1, ret2 -} - -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) SwitchContext(_param0 string) error { if mock == nil { panic("mock must not be nil. Use myMock := NewMockConnection().") } params := []pegomock.Param{_param0} - pegomock.GetGenericMockFrom(mock).Invoke("SwitchContext", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()}) - - return nil + result := pegomock.GetGenericMockFrom(mock).Invoke("SwitchContext", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()}) + var ret0 error + if len(result) != 0 { + if result[0] != nil { + ret0 = result[0].(error) + } + } + return ret0 } func (mock *MockConnection) ValidNamespaces() ([]v1.Namespace, error) { @@ -378,6 +341,40 @@ type VerifierMockConnection struct { timeout time.Duration } +func (verifier *VerifierMockConnection) ActiveCluster() *MockConnection_ActiveCluster_OngoingVerification { + params := []pegomock.Param{} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "ActiveCluster", params, verifier.timeout) + return &MockConnection_ActiveCluster_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} +} + +type MockConnection_ActiveCluster_OngoingVerification struct { + mock *MockConnection + methodInvocations []pegomock.MethodInvocation +} + +func (c *MockConnection_ActiveCluster_OngoingVerification) GetCapturedArguments() { +} + +func (c *MockConnection_ActiveCluster_OngoingVerification) GetAllCapturedArguments() { +} + +func (verifier *VerifierMockConnection) ActiveNamespace() *MockConnection_ActiveNamespace_OngoingVerification { + params := []pegomock.Param{} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "ActiveNamespace", params, verifier.timeout) + return &MockConnection_ActiveNamespace_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} +} + +type MockConnection_ActiveNamespace_OngoingVerification struct { + mock *MockConnection + methodInvocations []pegomock.MethodInvocation +} + +func (c *MockConnection_ActiveNamespace_OngoingVerification) GetCapturedArguments() { +} + +func (c *MockConnection_ActiveNamespace_OngoingVerification) GetAllCapturedArguments() { +} + func (verifier *VerifierMockConnection) CachedDiscovery() *MockConnection_CachedDiscovery_OngoingVerification { params := []pegomock.Param{} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "CachedDiscovery", params, verifier.timeout) @@ -414,15 +411,15 @@ func (c *MockConnection_CanI_OngoingVerification) GetCapturedArguments() (string func (c *MockConnection_CanI_OngoingVerification) GetAllCapturedArguments() (_param0 []string, _param1 []string, _param2 [][]string) { params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) if len(params) > 0 { - _param0 = make([]string, len(params[0])) + _param0 = make([]string, len(c.methodInvocations)) for u, param := range params[0] { _param0[u] = param.(string) } - _param1 = make([]string, len(params[1])) + _param1 = make([]string, len(c.methodInvocations)) for u, param := range params[1] { _param1[u] = param.(string) } - _param2 = make([][]string, len(params[2])) + _param2 = make([][]string, len(c.methodInvocations)) for u, param := range params[2] { _param2[u] = param.([]string) } @@ -430,6 +427,23 @@ func (c *MockConnection_CanI_OngoingVerification) GetAllCapturedArguments() (_pa return } +func (verifier *VerifierMockConnection) CheckConnectivity() *MockConnection_CheckConnectivity_OngoingVerification { + params := []pegomock.Param{} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "CheckConnectivity", params, verifier.timeout) + return &MockConnection_CheckConnectivity_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} +} + +type MockConnection_CheckConnectivity_OngoingVerification struct { + mock *MockConnection + methodInvocations []pegomock.MethodInvocation +} + +func (c *MockConnection_CheckConnectivity_OngoingVerification) GetCapturedArguments() { +} + +func (c *MockConnection_CheckConnectivity_OngoingVerification) GetAllCapturedArguments() { +} + func (verifier *VerifierMockConnection) Config() *MockConnection_Config_OngoingVerification { params := []pegomock.Param{} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Config", params, verifier.timeout) @@ -447,55 +461,55 @@ func (c *MockConnection_Config_OngoingVerification) GetCapturedArguments() { func (c *MockConnection_Config_OngoingVerification) GetAllCapturedArguments() { } -func (verifier *VerifierMockConnection) CurrentNamespaceName() *MockConnection_CurrentNamespaceName_OngoingVerification { +func (verifier *VerifierMockConnection) ConnectionOK() *MockConnection_ConnectionOK_OngoingVerification { params := []pegomock.Param{} - methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "CurrentNamespaceName", params, verifier.timeout) - return &MockConnection_CurrentNamespaceName_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "ConnectionOK", params, verifier.timeout) + return &MockConnection_ConnectionOK_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } -type MockConnection_CurrentNamespaceName_OngoingVerification struct { +type MockConnection_ConnectionOK_OngoingVerification struct { mock *MockConnection methodInvocations []pegomock.MethodInvocation } -func (c *MockConnection_CurrentNamespaceName_OngoingVerification) GetCapturedArguments() { +func (c *MockConnection_ConnectionOK_OngoingVerification) GetCapturedArguments() { } -func (c *MockConnection_CurrentNamespaceName_OngoingVerification) GetAllCapturedArguments() { +func (c *MockConnection_ConnectionOK_OngoingVerification) GetAllCapturedArguments() { } -func (verifier *VerifierMockConnection) DialOrDie() *MockConnection_DialOrDie_OngoingVerification { +func (verifier *VerifierMockConnection) Dial() *MockConnection_Dial_OngoingVerification { params := []pegomock.Param{} - methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "DialOrDie", params, verifier.timeout) - return &MockConnection_DialOrDie_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Dial", params, verifier.timeout) + return &MockConnection_Dial_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } -type MockConnection_DialOrDie_OngoingVerification struct { +type MockConnection_Dial_OngoingVerification struct { mock *MockConnection methodInvocations []pegomock.MethodInvocation } -func (c *MockConnection_DialOrDie_OngoingVerification) GetCapturedArguments() { +func (c *MockConnection_Dial_OngoingVerification) GetCapturedArguments() { } -func (c *MockConnection_DialOrDie_OngoingVerification) GetAllCapturedArguments() { +func (c *MockConnection_Dial_OngoingVerification) GetAllCapturedArguments() { } -func (verifier *VerifierMockConnection) DynDialOrDie() *MockConnection_DynDialOrDie_OngoingVerification { +func (verifier *VerifierMockConnection) DynDial() *MockConnection_DynDial_OngoingVerification { params := []pegomock.Param{} - methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "DynDialOrDie", params, verifier.timeout) - return &MockConnection_DynDialOrDie_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "DynDial", params, verifier.timeout) + return &MockConnection_DynDial_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } -type MockConnection_DynDialOrDie_OngoingVerification struct { +type MockConnection_DynDial_OngoingVerification struct { mock *MockConnection methodInvocations []pegomock.MethodInvocation } -func (c *MockConnection_DynDialOrDie_OngoingVerification) GetCapturedArguments() { +func (c *MockConnection_DynDial_OngoingVerification) GetCapturedArguments() { } -func (c *MockConnection_DynDialOrDie_OngoingVerification) GetAllCapturedArguments() { +func (c *MockConnection_DynDial_OngoingVerification) GetAllCapturedArguments() { } func (verifier *VerifierMockConnection) HasMetrics() *MockConnection_HasMetrics_OngoingVerification { @@ -515,26 +529,26 @@ func (c *MockConnection_HasMetrics_OngoingVerification) GetCapturedArguments() { func (c *MockConnection_HasMetrics_OngoingVerification) GetAllCapturedArguments() { } -func (verifier *VerifierMockConnection) IsNamespaced(_param0 string) *MockConnection_IsNamespaced_OngoingVerification { +func (verifier *VerifierMockConnection) IsActiveNamespace(_param0 string) *MockConnection_IsActiveNamespace_OngoingVerification { params := []pegomock.Param{_param0} - methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "IsNamespaced", params, verifier.timeout) - return &MockConnection_IsNamespaced_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "IsActiveNamespace", params, verifier.timeout) + return &MockConnection_IsActiveNamespace_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } -type MockConnection_IsNamespaced_OngoingVerification struct { +type MockConnection_IsActiveNamespace_OngoingVerification struct { mock *MockConnection methodInvocations []pegomock.MethodInvocation } -func (c *MockConnection_IsNamespaced_OngoingVerification) GetCapturedArguments() string { +func (c *MockConnection_IsActiveNamespace_OngoingVerification) GetCapturedArguments() string { _param0 := c.GetAllCapturedArguments() return _param0[len(_param0)-1] } -func (c *MockConnection_IsNamespaced_OngoingVerification) GetAllCapturedArguments() (_param0 []string) { +func (c *MockConnection_IsActiveNamespace_OngoingVerification) GetAllCapturedArguments() (_param0 []string) { params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) if len(params) > 0 { - _param0 = make([]string, len(params[0])) + _param0 = make([]string, len(c.methodInvocations)) for u, param := range params[0] { _param0[u] = param.(string) } @@ -559,48 +573,21 @@ func (c *MockConnection_MXDial_OngoingVerification) GetCapturedArguments() { func (c *MockConnection_MXDial_OngoingVerification) GetAllCapturedArguments() { } -func (verifier *VerifierMockConnection) NodePods(_param0 string) *MockConnection_NodePods_OngoingVerification { - params := []pegomock.Param{_param0} - methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "NodePods", params, verifier.timeout) - return &MockConnection_NodePods_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} -} - -type MockConnection_NodePods_OngoingVerification struct { - mock *MockConnection - methodInvocations []pegomock.MethodInvocation -} - -func (c *MockConnection_NodePods_OngoingVerification) GetCapturedArguments() string { - _param0 := c.GetAllCapturedArguments() - return _param0[len(_param0)-1] -} - -func (c *MockConnection_NodePods_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 *VerifierMockConnection) RestConfigOrDie() *MockConnection_RestConfigOrDie_OngoingVerification { +func (verifier *VerifierMockConnection) RestConfig() *MockConnection_RestConfig_OngoingVerification { params := []pegomock.Param{} - methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "RestConfigOrDie", params, verifier.timeout) - return &MockConnection_RestConfigOrDie_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "RestConfig", params, verifier.timeout) + return &MockConnection_RestConfig_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } -type MockConnection_RestConfigOrDie_OngoingVerification struct { +type MockConnection_RestConfig_OngoingVerification struct { mock *MockConnection methodInvocations []pegomock.MethodInvocation } -func (c *MockConnection_RestConfigOrDie_OngoingVerification) GetCapturedArguments() { +func (c *MockConnection_RestConfig_OngoingVerification) GetCapturedArguments() { } -func (c *MockConnection_RestConfigOrDie_OngoingVerification) GetAllCapturedArguments() { +func (c *MockConnection_RestConfig_OngoingVerification) GetAllCapturedArguments() { } func (verifier *VerifierMockConnection) ServerVersion() *MockConnection_ServerVersion_OngoingVerification { @@ -620,84 +607,26 @@ func (c *MockConnection_ServerVersion_OngoingVerification) GetCapturedArguments( func (c *MockConnection_ServerVersion_OngoingVerification) GetAllCapturedArguments() { } -func (verifier *VerifierMockConnection) SupportsRes(_param0 string, _param1 []string) *MockConnection_SupportsRes_OngoingVerification { - params := []pegomock.Param{_param0, _param1} - methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "SupportsRes", params, verifier.timeout) - return &MockConnection_SupportsRes_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} -} - -type MockConnection_SupportsRes_OngoingVerification struct { - mock *MockConnection - methodInvocations []pegomock.MethodInvocation -} - -func (c *MockConnection_SupportsRes_OngoingVerification) GetCapturedArguments() (string, []string) { - _param0, _param1 := c.GetAllCapturedArguments() - return _param0[len(_param0)-1], _param1[len(_param1)-1] -} - -func (c *MockConnection_SupportsRes_OngoingVerification) GetAllCapturedArguments() (_param0 []string, _param1 [][]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) - } - _param1 = make([][]string, len(params[1])) - for u, param := range params[1] { - _param1[u] = param.([]string) - } - } - return -} - -func (verifier *VerifierMockConnection) SupportsResource(_param0 string) *MockConnection_SupportsResource_OngoingVerification { +func (verifier *VerifierMockConnection) SwitchContext(_param0 string) *MockConnection_SwitchContext_OngoingVerification { params := []pegomock.Param{_param0} - methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "SupportsResource", params, verifier.timeout) - return &MockConnection_SupportsResource_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "SwitchContext", params, verifier.timeout) + return &MockConnection_SwitchContext_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } -type MockConnection_SupportsResource_OngoingVerification struct { +type MockConnection_SwitchContext_OngoingVerification struct { mock *MockConnection methodInvocations []pegomock.MethodInvocation } -func (c *MockConnection_SupportsResource_OngoingVerification) GetCapturedArguments() string { +func (c *MockConnection_SwitchContext_OngoingVerification) GetCapturedArguments() string { _param0 := c.GetAllCapturedArguments() return _param0[len(_param0)-1] } -func (c *MockConnection_SupportsResource_OngoingVerification) GetAllCapturedArguments() (_param0 []string) { +func (c *MockConnection_SwitchContext_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 *VerifierMockConnection) SwitchContextOrDie(_param0 string) *MockConnection_SwitchContextOrDie_OngoingVerification { - params := []pegomock.Param{_param0} - methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "SwitchContextOrDie", params, verifier.timeout) - return &MockConnection_SwitchContextOrDie_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} -} - -type MockConnection_SwitchContextOrDie_OngoingVerification struct { - mock *MockConnection - methodInvocations []pegomock.MethodInvocation -} - -func (c *MockConnection_SwitchContextOrDie_OngoingVerification) GetCapturedArguments() string { - _param0 := c.GetAllCapturedArguments() - return _param0[len(_param0)-1] -} - -func (c *MockConnection_SwitchContextOrDie_OngoingVerification) GetAllCapturedArguments() (_param0 []string) { - params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) - if len(params) > 0 { - _param0 = make([]string, len(params[0])) + _param0 = make([]string, len(c.methodInvocations)) for u, param := range params[0] { _param0[u] = param.(string) } diff --git a/internal/dao/alias_test.go b/internal/dao/alias_test.go index 0924ee27..f5b9fbb7 100644 --- a/internal/dao/alias_test.go +++ b/internal/dao/alias_test.go @@ -57,8 +57,8 @@ func (f testFactory) Get(gvr, path string, wait bool, sel labels.Selector) (runt func (f testFactory) List(gvr, ns string, wait bool, sel labels.Selector) ([]runtime.Object, error) { return nil, nil } -func (f testFactory) ForResource(ns, gvr string) informers.GenericInformer { - return nil +func (f testFactory) ForResource(ns, gvr string) (informers.GenericInformer, error) { + return nil, nil } func (f testFactory) CanForResource(ns, gvr string, verbs []string) (informers.GenericInformer, error) { return nil, nil diff --git a/internal/dao/container_test.go b/internal/dao/container_test.go index b10d7ee3..7f58796c 100644 --- a/internal/dao/container_test.go +++ b/internal/dao/container_test.go @@ -42,18 +42,19 @@ func makeConn() *conn { return &conn{} } -func (c *conn) Config() *client.Config { return nil } -func (c *conn) DialOrDie() kubernetes.Interface { return nil } -func (c *conn) SwitchContext(ctx string) error { return nil } -func (c *conn) CachedDiscoveryOrDie() *disk.CachedDiscoveryClient { return nil } -func (c *conn) RestConfigOrDie() *restclient.Config { return nil } -func (c *conn) MXDial() (*versioned.Clientset, error) { return nil, nil } -func (c *conn) DynDialOrDie() dynamic.Interface { return nil } -func (c *conn) HasMetrics() bool { return false } -func (c *conn) CheckConnectivity() bool { return false } -func (c *conn) IsNamespaced(n string) bool { return false } -func (c *conn) SupportsResource(group string) bool { return false } -func (c *conn) ValidNamespaces() ([]v1.Namespace, error) { return nil, nil } +func (c *conn) Config() *client.Config { return nil } +func (c *conn) Dial() (kubernetes.Interface, error) { return nil, nil } +func (c *conn) ConnectionOK() bool { return true } +func (c *conn) SwitchContext(ctx string) error { return nil } +func (c *conn) CachedDiscovery() (*disk.CachedDiscoveryClient, error) { return nil, nil } +func (c *conn) RestConfig() (*restclient.Config, error) { return nil, nil } +func (c *conn) MXDial() (*versioned.Clientset, error) { return nil, nil } +func (c *conn) DynDial() (dynamic.Interface, error) { return nil, nil } +func (c *conn) HasMetrics() bool { return false } +func (c *conn) CheckConnectivity() bool { return false } +func (c *conn) IsNamespaced(n string) bool { return false } +func (c *conn) SupportsResource(group string) bool { return false } +func (c *conn) ValidNamespaces() ([]v1.Namespace, error) { return nil, nil } func (c *conn) SupportsRes(grp string, versions []string) (string, bool, error) { return "", false, nil } @@ -81,7 +82,7 @@ func (f podFactory) Get(gvr, path string, wait bool, sel labels.Selector) (runti func (f podFactory) List(gvr, ns string, wait bool, sel labels.Selector) ([]runtime.Object, error) { return nil, nil } -func (f podFactory) ForResource(ns, gvr string) informers.GenericInformer { return nil } +func (f podFactory) ForResource(ns, gvr string) (informers.GenericInformer, error) { return nil, nil } func (f podFactory) CanForResource(ns, gvr string, verbs []string) (informers.GenericInformer, error) { return nil, nil } diff --git a/internal/dao/crd.go b/internal/dao/crd.go index c329560f..27aaff93 100644 --- a/internal/dao/crd.go +++ b/internal/dao/crd.go @@ -27,5 +27,5 @@ func (c *CustomResourceDefinition) List(ctx context.Context, _ string) ([]runtim } const gvr = "apiextensions.k8s.io/v1beta1/customresourcedefinitions" - return c.Factory.List(gvr, "-", true, labelSel) + return c.Factory.List(gvr, "-", false, labelSel) } diff --git a/internal/dao/cronjob.go b/internal/dao/cronjob.go index b11efb30..c93fdc6d 100644 --- a/internal/dao/cronjob.go +++ b/internal/dao/cronjob.go @@ -66,7 +66,11 @@ func (c *CronJob) Run(path string) error { }, Spec: cj.Spec.JobTemplate.Spec, } - _, err = c.Client().DialOrDie().BatchV1().Jobs(ns).Create(ctx, job, metav1.CreateOptions{}) + dial, err := c.Client().Dial() + if err != nil { + return err + } + _, err = dial.BatchV1().Jobs(ns).Create(ctx, job, metav1.CreateOptions{}) return err } diff --git a/internal/dao/dp.go b/internal/dao/dp.go index b0304085..1f425cb9 100644 --- a/internal/dao/dp.go +++ b/internal/dao/dp.go @@ -47,12 +47,16 @@ func (d *Deployment) Scale(ctx context.Context, path string, replicas int32) err return fmt.Errorf("user is not authorized to scale a deployment") } - scale, err := d.Client().DialOrDie().AppsV1().Deployments(ns).GetScale(ctx, n, metav1.GetOptions{}) + dial, err := d.Client().Dial() + if err != nil { + return err + } + scale, err := dial.AppsV1().Deployments(ns).GetScale(ctx, n, metav1.GetOptions{}) if err != nil { return err } scale.Spec.Replicas = replicas - _, err = d.Client().DialOrDie().AppsV1().Deployments(ns).UpdateScale(ctx, n, scale, metav1.UpdateOptions{}) + _, err = dial.AppsV1().Deployments(ns).UpdateScale(ctx, n, scale, metav1.UpdateOptions{}) return err } @@ -77,7 +81,11 @@ func (d *Deployment) Restart(ctx context.Context, path string) error { return err } - _, err = d.Client().DialOrDie().AppsV1().Deployments(dp.Namespace).Patch( + dial, err := d.Client().Dial() + if err != nil { + return err + } + _, err = dial.AppsV1().Deployments(dp.Namespace).Patch( ctx, dp.Name, types.StrategicMergePatchType, diff --git a/internal/dao/ds.go b/internal/dao/ds.go index 19c4b7d5..a3ead752 100644 --- a/internal/dao/ds.go +++ b/internal/dao/ds.go @@ -57,7 +57,11 @@ func (d *DaemonSet) Restart(ctx context.Context, path string) error { return err } - _, err = d.Client().DialOrDie().AppsV1().DaemonSets(ds.Namespace).Patch( + dial, err := d.Client().Dial() + if err != nil { + return err + } + _, err = dial.AppsV1().DaemonSets(ds.Namespace).Patch( ctx, ds.Name, types.StrategicMergePatchType, diff --git a/internal/dao/generic.go b/internal/dao/generic.go index 1a8078ae..e04e60f8 100644 --- a/internal/dao/generic.go +++ b/internal/dao/generic.go @@ -38,10 +38,15 @@ func (g *Generic) List(ctx context.Context, ns string) ([]runtime.Object, error) ll *unstructured.UnstructuredList err error ) + dial, err := g.dynClient() + if err != nil { + return nil, err + } + if client.IsClusterScoped(ns) { - ll, err = g.dynClient().List(ctx, metav1.ListOptions{LabelSelector: labelSel}) + ll, err = dial.List(ctx, metav1.ListOptions{LabelSelector: labelSel}) } else { - ll, err = g.dynClient().Namespace(ns).List(ctx, metav1.ListOptions{LabelSelector: labelSel}) + ll, err = dial.Namespace(ns).List(ctx, metav1.ListOptions{LabelSelector: labelSel}) } if err != nil { return nil, err @@ -59,7 +64,10 @@ func (g *Generic) List(ctx context.Context, ns string) ([]runtime.Object, error) func (g *Generic) Get(ctx context.Context, path string) (runtime.Object, error) { var opts metav1.GetOptions ns, n := client.Namespaced(path) - dial := g.dynClient() + dial, err := g.dynClient() + if err != nil { + return nil, err + } if client.IsClusterScoped(ns) { return dial.Get(ctx, n, opts) } @@ -113,13 +121,23 @@ func (g *Generic) Delete(path string, cascade, force bool) error { // BOZO!! Move to caller! ctx, cancel := context.WithTimeout(context.Background(), client.CallTimeout) defer cancel() + + dial, err := g.dynClient() + if err != nil { + return err + } if client.IsClusterScoped(ns) { - return g.dynClient().Delete(ctx, n, opts) + return dial.Delete(ctx, n, opts) } - return g.dynClient().Namespace(ns).Delete(ctx, n, opts) + return dial.Namespace(ns).Delete(ctx, n, opts) } -func (g *Generic) dynClient() dynamic.NamespaceableResourceInterface { - return g.Client().DynDialOrDie().Resource(g.gvr.GVR()) +func (g *Generic) dynClient() (dynamic.NamespaceableResourceInterface, error) { + dial, err := g.Client().DynDial() + if err != nil { + return nil, err + } + + return dial.Resource(g.gvr.GVR()), nil } diff --git a/internal/dao/node.go b/internal/dao/node.go index 19d7b0f3..e46e7d7b 100644 --- a/internal/dao/node.go +++ b/internal/dao/node.go @@ -52,7 +52,12 @@ func (n *Node) ToggleCordon(path string, cordon bool) error { } return fmt.Errorf("node is already uncordoned") } - err, patchErr := h.PatchOrReplace(n.Factory.Client().DialOrDie(), false) + dial, err := n.Factory.Client().Dial() + if err != nil { + return err + } + + err, patchErr := h.PatchOrReplace(dial, false) if patchErr != nil { return patchErr } @@ -79,7 +84,11 @@ func (o DrainOptions) toDrainHelper(k kubernetes.Interface, w io.Writer) drain.H func (n *Node) Drain(path string, opts DrainOptions, w io.Writer) error { _ = n.ToggleCordon(path, true) - h := opts.toDrainHelper(n.Factory.Client().DialOrDie(), w) + dial, err := n.Factory.Client().Dial() + if err != nil { + return err + } + h := opts.toDrainHelper(dial, w) dd, errs := h.GetPodsForDeletion(path) if len(errs) != 0 { for _, e := range errs { @@ -174,7 +183,11 @@ func FetchNode(ctx context.Context, f Factory, path string) (*v1.Node, error) { return nil, fmt.Errorf("user is not authorized to list nodes") } - return f.Client().DialOrDie().CoreV1().Nodes().Get(ctx, path, metav1.GetOptions{}) + dial, err := f.Client().Dial() + if err != nil { + return nil, err + } + return dial.CoreV1().Nodes().Get(ctx, path, metav1.GetOptions{}) } // FetchNodes retrieves all nodes. @@ -187,7 +200,11 @@ func FetchNodes(ctx context.Context, f Factory, labelsSel string) (*v1.NodeList, return nil, fmt.Errorf("user is not authorized to list nodes") } - return f.Client().DialOrDie().CoreV1().Nodes().List(ctx, metav1.ListOptions{ + dial, err := f.Client().Dial() + if err != nil { + return nil, err + } + return dial.CoreV1().Nodes().List(ctx, metav1.ListOptions{ LabelSelector: labelsSel, }) } diff --git a/internal/dao/pod.go b/internal/dao/pod.go index 2bd4bca6..4b624496 100644 --- a/internal/dao/pod.go +++ b/internal/dao/pod.go @@ -123,8 +123,12 @@ func (p *Pod) Logs(path string, opts *v1.PodLogOptions) (*restclient.Request, er return nil, fmt.Errorf("user is not authorized to view pod logs") } + dial, err := p.Client().Dial() + if err != nil { + return nil, err + } ns, n := client.Namespaced(path) - return p.Client().DialOrDie().CoreV1().Pods(ns).GetLogs(n, opts), nil + return dial.CoreV1().Pods(ns).GetLogs(n, opts), nil } // Containers returns all container names on pod diff --git a/internal/dao/port_forwarder.go b/internal/dao/port_forwarder.go index dd4d0a83..12316cea 100644 --- a/internal/dao/port_forwarder.go +++ b/internal/dao/port_forwarder.go @@ -134,14 +134,16 @@ func (p *PortForwarder) Start(path, co string, t client.PortTunnel) (*portforwar return nil, fmt.Errorf("user is not authorized to update portforward") } - rcfg := p.Client().RestConfigOrDie() - rcfg.GroupVersion = &schema.GroupVersion{Group: "", Version: "v1"} - rcfg.APIPath = "/api" - codec, _ := codec() - rcfg.NegotiatedSerializer = codec.WithoutConversion() - clt, err := rest.RESTClientFor(rcfg) + cfg, err := p.Client().RestConfig() + if err != nil { + return nil, err + } + cfg.GroupVersion = &schema.GroupVersion{Group: "", Version: "v1"} + cfg.APIPath = "/api" + codec, _ := codec() + cfg.NegotiatedSerializer = codec.WithoutConversion() + clt, err := rest.RESTClientFor(cfg) if err != nil { - log.Debug().Msgf("Boom! %#v", err) return nil, err } req := clt.Post(). diff --git a/internal/dao/registry.go b/internal/dao/registry.go index 7310effd..850ab933 100644 --- a/internal/dao/registry.go +++ b/internal/dao/registry.go @@ -274,7 +274,16 @@ func loadRBAC(m ResourceMetas) { } func loadPreferred(f Factory, m ResourceMetas) error { - rr, err := f.Client().CachedDiscoveryOrDie().ServerPreferredResources() + if !f.Client().ConnectionOK() { + log.Error().Msgf("no API server connection") + return nil + } + + dial, err := f.Client().CachedDiscovery() + if err != nil { + return err + } + rr, err := dial.ServerPreferredResources() if err != nil { log.Debug().Err(err).Msgf("Failed to load preferred resources") } @@ -294,7 +303,7 @@ func loadPreferred(f Factory, m ResourceMetas) error { func loadCRDs(f Factory, m ResourceMetas) { const crdGVR = "apiextensions.k8s.io/v1beta1/customresourcedefinitions" - oo, err := f.List(crdGVR, client.ClusterScope, true, labels.Everything()) + oo, err := f.List(crdGVR, client.ClusterScope, false, labels.Everything()) if err != nil { log.Warn().Err(err).Msgf("Fail CRDs load") return diff --git a/internal/dao/rest_mapper.go b/internal/dao/rest_mapper.go index 66485c27..e9780dd3 100644 --- a/internal/dao/rest_mapper.go +++ b/internal/dao/rest_mapper.go @@ -20,7 +20,10 @@ type RestMapper struct { // ToRESTMapper map resources to kind, and map kind and version to interfaces for manipulating K8s objects. func (r *RestMapper) ToRESTMapper() (meta.RESTMapper, error) { - dial := r.CachedDiscoveryOrDie() + dial, err := r.CachedDiscovery() + if err != nil { + return nil, err + } mapper := restmapper.NewDeferredDiscoveryRESTMapper(dial) expander := restmapper.NewShortcutExpander(mapper, dial) diff --git a/internal/dao/rs.go b/internal/dao/rs.go index 0ab1c7c4..22354b2d 100644 --- a/internal/dao/rs.go +++ b/internal/dao/rs.go @@ -80,10 +80,15 @@ func (r *ReplicaSet) Rollback(fqn string) error { if err != nil { return err } + dial, err := r.Client().Dial() + if err != nil { + return err + } + rb, err := polymorphichelpers.RollbackerFor(schema.GroupKind{ Group: apiGroup, Kind: kind}, - r.Client().DialOrDie(), + dial, ) if err != nil { return err diff --git a/internal/dao/sts.go b/internal/dao/sts.go index 2706b24a..fe693c34 100644 --- a/internal/dao/sts.go +++ b/internal/dao/sts.go @@ -46,12 +46,16 @@ func (s *StatefulSet) Scale(ctx context.Context, path string, replicas int32) er return fmt.Errorf("user is not authorized to scale statefulsets") } - scale, err := s.Client().DialOrDie().AppsV1().StatefulSets(ns).GetScale(ctx, n, metav1.GetOptions{}) + dial, err := s.Client().Dial() + if err != nil { + return err + } + scale, err := dial.AppsV1().StatefulSets(ns).GetScale(ctx, n, metav1.GetOptions{}) if err != nil { return err } scale.Spec.Replicas = replicas - _, err = s.Client().DialOrDie().AppsV1().StatefulSets(ns).UpdateScale(ctx, n, scale, metav1.UpdateOptions{}) + _, err = dial.AppsV1().StatefulSets(ns).UpdateScale(ctx, n, scale, metav1.UpdateOptions{}) return err } @@ -77,7 +81,11 @@ func (s *StatefulSet) Restart(ctx context.Context, path string) error { return err } - _, err = s.Client().DialOrDie().AppsV1().StatefulSets(sts.Namespace).Patch( + dial, err := s.Client().Dial() + if err != nil { + return err + } + _, err = dial.AppsV1().StatefulSets(sts.Namespace).Patch( ctx, sts.Name, types.StrategicMergePatchType, diff --git a/internal/dao/table.go b/internal/dao/table.go index 444ed79e..772eae03 100644 --- a/internal/dao/table.go +++ b/internal/dao/table.go @@ -73,20 +73,24 @@ func (t *Table) List(ctx context.Context, ns string) ([]runtime.Object, error) { const gvFmt = "application/json;as=Table;v=%s;g=%s, application/json" func (t *Table) getClient() (*rest.RESTClient, error) { - crConfig := t.Client().RestConfigOrDie() - gv := t.gvr.GV() - crConfig.GroupVersion = &gv - crConfig.APIPath = "/apis" - if t.gvr.G() == "" { - crConfig.APIPath = "/api" - } - codec, _ := t.codec() - crConfig.NegotiatedSerializer = codec.WithoutConversion() - - crRestClient, err := rest.RESTClientFor(crConfig) + cfg, err := t.Client().RestConfig() if err != nil { return nil, err } + gv := t.gvr.GV() + cfg.GroupVersion = &gv + cfg.APIPath = "/apis" + if t.gvr.G() == "" { + cfg.APIPath = "/api" + } + codec, _ := t.codec() + cfg.NegotiatedSerializer = codec.WithoutConversion() + + crRestClient, err := rest.RESTClientFor(cfg) + if err != nil { + return nil, err + } + return crRestClient, nil } diff --git a/internal/dao/types.go b/internal/dao/types.go index 0362f19d..ddf671a6 100644 --- a/internal/dao/types.go +++ b/internal/dao/types.go @@ -33,7 +33,7 @@ type Factory interface { List(gvr, ns string, wait bool, sel labels.Selector) ([]runtime.Object, error) // ForResource fetch an informer for a given resource. - ForResource(ns, gvr string) informers.GenericInformer + ForResource(ns, gvr string) (informers.GenericInformer, error) // CanForResource fetch an informer for a given resource if authorized CanForResource(ns, gvr string, verbs []string) (informers.GenericInformer, error) diff --git a/internal/model/log_test.go b/internal/model/log_test.go index 9859a4f2..36ed5806 100644 --- a/internal/model/log_test.go +++ b/internal/model/log_test.go @@ -250,8 +250,8 @@ func (f testFactory) Get(gvr, path string, wait bool, sel labels.Selector) (runt func (f testFactory) List(gvr, ns string, wait bool, sel labels.Selector) ([]runtime.Object, error) { return nil, nil } -func (f testFactory) ForResource(ns, gvr string) informers.GenericInformer { - return nil +func (f testFactory) ForResource(ns, gvr string) (informers.GenericInformer, error) { + return nil, nil } func (f testFactory) CanForResource(ns, gvr string, verbs []string) (informers.GenericInformer, error) { return nil, nil diff --git a/internal/model/mock_connection_test.go b/internal/model/mock_connection_test.go index f60e861f..9ce08a7e 100644 --- a/internal/model/mock_connection_test.go +++ b/internal/model/mock_connection_test.go @@ -4,9 +4,6 @@ package model_test import ( - "reflect" - "time" - client "github.com/derailed/k9s/internal/client" pegomock "github.com/petergtz/pegomock" v1 "k8s.io/api/core/v1" @@ -16,6 +13,8 @@ import ( 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 { @@ -33,6 +32,36 @@ func NewMockConnection(options ...pegomock.Option) *MockConnection { func (mock *MockConnection) SetFailHandler(fh pegomock.FailHandler) { mock.fail = fh } func (mock *MockConnection) FailHandler() pegomock.FailHandler { return mock.fail } +func (mock *MockConnection) ActiveCluster() string { + if mock == nil { + panic("mock must not be nil. Use myMock := NewMockConnection().") + } + params := []pegomock.Param{} + result := pegomock.GetGenericMockFrom(mock).Invoke("ActiveCluster", params, []reflect.Type{reflect.TypeOf((*string)(nil)).Elem()}) + var ret0 string + if len(result) != 0 { + if result[0] != nil { + ret0 = result[0].(string) + } + } + return ret0 +} + +func (mock *MockConnection) ActiveNamespace() string { + if mock == nil { + panic("mock must not be nil. Use myMock := NewMockConnection().") + } + params := []pegomock.Param{} + result := pegomock.GetGenericMockFrom(mock).Invoke("ActiveNamespace", params, []reflect.Type{reflect.TypeOf((*string)(nil)).Elem()}) + var ret0 string + if len(result) != 0 { + if result[0] != nil { + ret0 = result[0].(string) + } + } + return ret0 +} + func (mock *MockConnection) CachedDiscovery() (*disk.CachedDiscoveryClient, error) { if mock == nil { panic("mock must not be nil. Use myMock := NewMockConnection().") @@ -71,6 +100,21 @@ func (mock *MockConnection) CanI(_param0 string, _param1 string, _param2 []strin return ret0, ret1 } +func (mock *MockConnection) CheckConnectivity() bool { + if mock == nil { + panic("mock must not be nil. Use myMock := NewMockConnection().") + } + params := []pegomock.Param{} + result := pegomock.GetGenericMockFrom(mock).Invoke("CheckConnectivity", 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) Config() *client.Config { if mock == nil { panic("mock must not be nil. Use myMock := NewMockConnection().") @@ -86,17 +130,32 @@ func (mock *MockConnection) Config() *client.Config { return ret0 } -func (mock *MockConnection) CurrentNamespaceName() (string, error) { +func (mock *MockConnection) ConnectionOK() bool { if mock == nil { panic("mock must not be nil. Use myMock := NewMockConnection().") } params := []pegomock.Param{} - result := pegomock.GetGenericMockFrom(mock).Invoke("CurrentNamespaceName", params, []reflect.Type{reflect.TypeOf((*string)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}) - var ret0 string + result := pegomock.GetGenericMockFrom(mock).Invoke("ConnectionOK", 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) Dial() (kubernetes.Interface, error) { + if mock == nil { + panic("mock must not be nil. Use myMock := NewMockConnection().") + } + params := []pegomock.Param{} + result := pegomock.GetGenericMockFrom(mock).Invoke("Dial", params, []reflect.Type{reflect.TypeOf((*kubernetes.Interface)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}) + var ret0 kubernetes.Interface var ret1 error if len(result) != 0 { if result[0] != nil { - ret0 = result[0].(string) + ret0 = result[0].(kubernetes.Interface) } if result[1] != nil { ret1 = result[1].(error) @@ -105,34 +164,23 @@ func (mock *MockConnection) CurrentNamespaceName() (string, error) { return ret0, ret1 } -func (mock *MockConnection) DialOrDie() kubernetes.Interface { +func (mock *MockConnection) DynDial() (dynamic.Interface, error) { 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()}) + result := pegomock.GetGenericMockFrom(mock).Invoke("DynDial", params, []reflect.Type{reflect.TypeOf((*dynamic.Interface)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}) var ret0 dynamic.Interface + var ret1 error if len(result) != 0 { if result[0] != nil { ret0 = result[0].(dynamic.Interface) } + if result[1] != nil { + ret1 = result[1].(error) + } } - return ret0 + return ret0, ret1 } func (mock *MockConnection) HasMetrics() bool { @@ -150,12 +198,12 @@ func (mock *MockConnection) HasMetrics() bool { return ret0 } -func (mock *MockConnection) IsNamespaced(_param0 string) bool { +func (mock *MockConnection) IsActiveNamespace(_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()}) + result := pegomock.GetGenericMockFrom(mock).Invoke("IsActiveNamespace", params, []reflect.Type{reflect.TypeOf((*bool)(nil)).Elem()}) var ret0 bool if len(result) != 0 { if result[0] != nil { @@ -184,17 +232,17 @@ func (mock *MockConnection) MXDial() (*versioned.Clientset, error) { return ret0, ret1 } -func (mock *MockConnection) NodePods(_param0 string) (*v1.PodList, error) { +func (mock *MockConnection) RestConfig() (*rest.Config, error) { if mock == nil { panic("mock must not be nil. Use myMock := NewMockConnection().") } - params := []pegomock.Param{_param0} - result := pegomock.GetGenericMockFrom(mock).Invoke("NodePods", params, []reflect.Type{reflect.TypeOf((**v1.PodList)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}) - var ret0 *v1.PodList + params := []pegomock.Param{} + result := pegomock.GetGenericMockFrom(mock).Invoke("RestConfig", params, []reflect.Type{reflect.TypeOf((**rest.Config)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}) + var ret0 *rest.Config var ret1 error if len(result) != 0 { if result[0] != nil { - ret0 = result[0].(*v1.PodList) + ret0 = result[0].(*rest.Config) } if result[1] != nil { ret1 = result[1].(error) @@ -203,21 +251,6 @@ func (mock *MockConnection) NodePods(_param0 string) (*v1.PodList, error) { return ret0, ret1 } -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) ServerVersion() (*version.Info, error) { if mock == nil { panic("mock must not be nil. Use myMock := NewMockConnection().") @@ -237,52 +270,21 @@ func (mock *MockConnection) ServerVersion() (*version.Info, error) { return ret0, ret1 } -func (mock *MockConnection) SupportsRes(_param0 string, _param1 []string) (string, bool, error) { - if mock == nil { - panic("mock must not be nil. Use myMock := NewMockConnection().") - } - params := []pegomock.Param{_param0, _param1} - result := pegomock.GetGenericMockFrom(mock).Invoke("SupportsRes", params, []reflect.Type{reflect.TypeOf((*string)(nil)).Elem(), reflect.TypeOf((*bool)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}) - var ret0 string - var ret1 bool - var ret2 error - if len(result) != 0 { - if result[0] != nil { - ret0 = result[0].(string) - } - if result[1] != nil { - ret1 = result[1].(bool) - } - if result[2] != nil { - ret2 = result[2].(error) - } - } - return ret0, ret1, ret2 -} - -func (mock *MockConnection) SupportsResource(_param0 string) bool { +func (mock *MockConnection) SwitchContext(_param0 string) error { 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 + result := pegomock.GetGenericMockFrom(mock).Invoke("SwitchContext", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()}) + var ret0 error if len(result) != 0 { if result[0] != nil { - ret0 = result[0].(bool) + ret0 = result[0].(error) } } 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().") @@ -339,6 +341,40 @@ type VerifierMockConnection struct { timeout time.Duration } +func (verifier *VerifierMockConnection) ActiveCluster() *MockConnection_ActiveCluster_OngoingVerification { + params := []pegomock.Param{} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "ActiveCluster", params, verifier.timeout) + return &MockConnection_ActiveCluster_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} +} + +type MockConnection_ActiveCluster_OngoingVerification struct { + mock *MockConnection + methodInvocations []pegomock.MethodInvocation +} + +func (c *MockConnection_ActiveCluster_OngoingVerification) GetCapturedArguments() { +} + +func (c *MockConnection_ActiveCluster_OngoingVerification) GetAllCapturedArguments() { +} + +func (verifier *VerifierMockConnection) ActiveNamespace() *MockConnection_ActiveNamespace_OngoingVerification { + params := []pegomock.Param{} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "ActiveNamespace", params, verifier.timeout) + return &MockConnection_ActiveNamespace_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} +} + +type MockConnection_ActiveNamespace_OngoingVerification struct { + mock *MockConnection + methodInvocations []pegomock.MethodInvocation +} + +func (c *MockConnection_ActiveNamespace_OngoingVerification) GetCapturedArguments() { +} + +func (c *MockConnection_ActiveNamespace_OngoingVerification) GetAllCapturedArguments() { +} + func (verifier *VerifierMockConnection) CachedDiscovery() *MockConnection_CachedDiscovery_OngoingVerification { params := []pegomock.Param{} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "CachedDiscovery", params, verifier.timeout) @@ -375,15 +411,15 @@ func (c *MockConnection_CanI_OngoingVerification) GetCapturedArguments() (string func (c *MockConnection_CanI_OngoingVerification) GetAllCapturedArguments() (_param0 []string, _param1 []string, _param2 [][]string) { params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) if len(params) > 0 { - _param0 = make([]string, len(params[0])) + _param0 = make([]string, len(c.methodInvocations)) for u, param := range params[0] { _param0[u] = param.(string) } - _param1 = make([]string, len(params[1])) + _param1 = make([]string, len(c.methodInvocations)) for u, param := range params[1] { _param1[u] = param.(string) } - _param2 = make([][]string, len(params[2])) + _param2 = make([][]string, len(c.methodInvocations)) for u, param := range params[2] { _param2[u] = param.([]string) } @@ -391,6 +427,23 @@ func (c *MockConnection_CanI_OngoingVerification) GetAllCapturedArguments() (_pa return } +func (verifier *VerifierMockConnection) CheckConnectivity() *MockConnection_CheckConnectivity_OngoingVerification { + params := []pegomock.Param{} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "CheckConnectivity", params, verifier.timeout) + return &MockConnection_CheckConnectivity_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} +} + +type MockConnection_CheckConnectivity_OngoingVerification struct { + mock *MockConnection + methodInvocations []pegomock.MethodInvocation +} + +func (c *MockConnection_CheckConnectivity_OngoingVerification) GetCapturedArguments() { +} + +func (c *MockConnection_CheckConnectivity_OngoingVerification) GetAllCapturedArguments() { +} + func (verifier *VerifierMockConnection) Config() *MockConnection_Config_OngoingVerification { params := []pegomock.Param{} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Config", params, verifier.timeout) @@ -408,55 +461,55 @@ func (c *MockConnection_Config_OngoingVerification) GetCapturedArguments() { func (c *MockConnection_Config_OngoingVerification) GetAllCapturedArguments() { } -func (verifier *VerifierMockConnection) CurrentNamespaceName() *MockConnection_CurrentNamespaceName_OngoingVerification { +func (verifier *VerifierMockConnection) ConnectionOK() *MockConnection_ConnectionOK_OngoingVerification { params := []pegomock.Param{} - methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "CurrentNamespaceName", params, verifier.timeout) - return &MockConnection_CurrentNamespaceName_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "ConnectionOK", params, verifier.timeout) + return &MockConnection_ConnectionOK_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } -type MockConnection_CurrentNamespaceName_OngoingVerification struct { +type MockConnection_ConnectionOK_OngoingVerification struct { mock *MockConnection methodInvocations []pegomock.MethodInvocation } -func (c *MockConnection_CurrentNamespaceName_OngoingVerification) GetCapturedArguments() { +func (c *MockConnection_ConnectionOK_OngoingVerification) GetCapturedArguments() { } -func (c *MockConnection_CurrentNamespaceName_OngoingVerification) GetAllCapturedArguments() { +func (c *MockConnection_ConnectionOK_OngoingVerification) GetAllCapturedArguments() { } -func (verifier *VerifierMockConnection) DialOrDie() *MockConnection_DialOrDie_OngoingVerification { +func (verifier *VerifierMockConnection) Dial() *MockConnection_Dial_OngoingVerification { params := []pegomock.Param{} - methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "DialOrDie", params, verifier.timeout) - return &MockConnection_DialOrDie_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Dial", params, verifier.timeout) + return &MockConnection_Dial_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } -type MockConnection_DialOrDie_OngoingVerification struct { +type MockConnection_Dial_OngoingVerification struct { mock *MockConnection methodInvocations []pegomock.MethodInvocation } -func (c *MockConnection_DialOrDie_OngoingVerification) GetCapturedArguments() { +func (c *MockConnection_Dial_OngoingVerification) GetCapturedArguments() { } -func (c *MockConnection_DialOrDie_OngoingVerification) GetAllCapturedArguments() { +func (c *MockConnection_Dial_OngoingVerification) GetAllCapturedArguments() { } -func (verifier *VerifierMockConnection) DynDialOrDie() *MockConnection_DynDialOrDie_OngoingVerification { +func (verifier *VerifierMockConnection) DynDial() *MockConnection_DynDial_OngoingVerification { params := []pegomock.Param{} - methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "DynDialOrDie", params, verifier.timeout) - return &MockConnection_DynDialOrDie_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "DynDial", params, verifier.timeout) + return &MockConnection_DynDial_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } -type MockConnection_DynDialOrDie_OngoingVerification struct { +type MockConnection_DynDial_OngoingVerification struct { mock *MockConnection methodInvocations []pegomock.MethodInvocation } -func (c *MockConnection_DynDialOrDie_OngoingVerification) GetCapturedArguments() { +func (c *MockConnection_DynDial_OngoingVerification) GetCapturedArguments() { } -func (c *MockConnection_DynDialOrDie_OngoingVerification) GetAllCapturedArguments() { +func (c *MockConnection_DynDial_OngoingVerification) GetAllCapturedArguments() { } func (verifier *VerifierMockConnection) HasMetrics() *MockConnection_HasMetrics_OngoingVerification { @@ -476,26 +529,26 @@ func (c *MockConnection_HasMetrics_OngoingVerification) GetCapturedArguments() { func (c *MockConnection_HasMetrics_OngoingVerification) GetAllCapturedArguments() { } -func (verifier *VerifierMockConnection) IsNamespaced(_param0 string) *MockConnection_IsNamespaced_OngoingVerification { +func (verifier *VerifierMockConnection) IsActiveNamespace(_param0 string) *MockConnection_IsActiveNamespace_OngoingVerification { params := []pegomock.Param{_param0} - methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "IsNamespaced", params, verifier.timeout) - return &MockConnection_IsNamespaced_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "IsActiveNamespace", params, verifier.timeout) + return &MockConnection_IsActiveNamespace_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } -type MockConnection_IsNamespaced_OngoingVerification struct { +type MockConnection_IsActiveNamespace_OngoingVerification struct { mock *MockConnection methodInvocations []pegomock.MethodInvocation } -func (c *MockConnection_IsNamespaced_OngoingVerification) GetCapturedArguments() string { +func (c *MockConnection_IsActiveNamespace_OngoingVerification) GetCapturedArguments() string { _param0 := c.GetAllCapturedArguments() return _param0[len(_param0)-1] } -func (c *MockConnection_IsNamespaced_OngoingVerification) GetAllCapturedArguments() (_param0 []string) { +func (c *MockConnection_IsActiveNamespace_OngoingVerification) GetAllCapturedArguments() (_param0 []string) { params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) if len(params) > 0 { - _param0 = make([]string, len(params[0])) + _param0 = make([]string, len(c.methodInvocations)) for u, param := range params[0] { _param0[u] = param.(string) } @@ -520,48 +573,21 @@ func (c *MockConnection_MXDial_OngoingVerification) GetCapturedArguments() { func (c *MockConnection_MXDial_OngoingVerification) GetAllCapturedArguments() { } -func (verifier *VerifierMockConnection) NodePods(_param0 string) *MockConnection_NodePods_OngoingVerification { - params := []pegomock.Param{_param0} - methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "NodePods", params, verifier.timeout) - return &MockConnection_NodePods_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} -} - -type MockConnection_NodePods_OngoingVerification struct { - mock *MockConnection - methodInvocations []pegomock.MethodInvocation -} - -func (c *MockConnection_NodePods_OngoingVerification) GetCapturedArguments() string { - _param0 := c.GetAllCapturedArguments() - return _param0[len(_param0)-1] -} - -func (c *MockConnection_NodePods_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 *VerifierMockConnection) RestConfigOrDie() *MockConnection_RestConfigOrDie_OngoingVerification { +func (verifier *VerifierMockConnection) RestConfig() *MockConnection_RestConfig_OngoingVerification { params := []pegomock.Param{} - methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "RestConfigOrDie", params, verifier.timeout) - return &MockConnection_RestConfigOrDie_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "RestConfig", params, verifier.timeout) + return &MockConnection_RestConfig_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } -type MockConnection_RestConfigOrDie_OngoingVerification struct { +type MockConnection_RestConfig_OngoingVerification struct { mock *MockConnection methodInvocations []pegomock.MethodInvocation } -func (c *MockConnection_RestConfigOrDie_OngoingVerification) GetCapturedArguments() { +func (c *MockConnection_RestConfig_OngoingVerification) GetCapturedArguments() { } -func (c *MockConnection_RestConfigOrDie_OngoingVerification) GetAllCapturedArguments() { +func (c *MockConnection_RestConfig_OngoingVerification) GetAllCapturedArguments() { } func (verifier *VerifierMockConnection) ServerVersion() *MockConnection_ServerVersion_OngoingVerification { @@ -581,84 +607,26 @@ func (c *MockConnection_ServerVersion_OngoingVerification) GetCapturedArguments( func (c *MockConnection_ServerVersion_OngoingVerification) GetAllCapturedArguments() { } -func (verifier *VerifierMockConnection) SupportsRes(_param0 string, _param1 []string) *MockConnection_SupportsRes_OngoingVerification { - params := []pegomock.Param{_param0, _param1} - methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "SupportsRes", params, verifier.timeout) - return &MockConnection_SupportsRes_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} -} - -type MockConnection_SupportsRes_OngoingVerification struct { - mock *MockConnection - methodInvocations []pegomock.MethodInvocation -} - -func (c *MockConnection_SupportsRes_OngoingVerification) GetCapturedArguments() (string, []string) { - _param0, _param1 := c.GetAllCapturedArguments() - return _param0[len(_param0)-1], _param1[len(_param1)-1] -} - -func (c *MockConnection_SupportsRes_OngoingVerification) GetAllCapturedArguments() (_param0 []string, _param1 [][]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) - } - _param1 = make([][]string, len(params[1])) - for u, param := range params[1] { - _param1[u] = param.([]string) - } - } - return -} - -func (verifier *VerifierMockConnection) SupportsResource(_param0 string) *MockConnection_SupportsResource_OngoingVerification { +func (verifier *VerifierMockConnection) SwitchContext(_param0 string) *MockConnection_SwitchContext_OngoingVerification { params := []pegomock.Param{_param0} - methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "SupportsResource", params, verifier.timeout) - return &MockConnection_SupportsResource_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "SwitchContext", params, verifier.timeout) + return &MockConnection_SwitchContext_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } -type MockConnection_SupportsResource_OngoingVerification struct { +type MockConnection_SwitchContext_OngoingVerification struct { mock *MockConnection methodInvocations []pegomock.MethodInvocation } -func (c *MockConnection_SupportsResource_OngoingVerification) GetCapturedArguments() string { +func (c *MockConnection_SwitchContext_OngoingVerification) GetCapturedArguments() string { _param0 := c.GetAllCapturedArguments() return _param0[len(_param0)-1] } -func (c *MockConnection_SupportsResource_OngoingVerification) GetAllCapturedArguments() (_param0 []string) { +func (c *MockConnection_SwitchContext_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 *VerifierMockConnection) SwitchContextOrDie(_param0 string) *MockConnection_SwitchContextOrDie_OngoingVerification { - params := []pegomock.Param{_param0} - methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "SwitchContextOrDie", params, verifier.timeout) - return &MockConnection_SwitchContextOrDie_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} -} - -type MockConnection_SwitchContextOrDie_OngoingVerification struct { - mock *MockConnection - methodInvocations []pegomock.MethodInvocation -} - -func (c *MockConnection_SwitchContextOrDie_OngoingVerification) GetCapturedArguments() string { - _param0 := c.GetAllCapturedArguments() - return _param0[len(_param0)-1] -} - -func (c *MockConnection_SwitchContextOrDie_OngoingVerification) GetAllCapturedArguments() (_param0 []string) { - params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) - if len(params) > 0 { - _param0 = make([]string, len(params[0])) + _param0 = make([]string, len(c.methodInvocations)) for u, param := range params[0] { _param0[u] = param.(string) } diff --git a/internal/model/table.go b/internal/model/table.go index c55d00b6..318ae2ba 100644 --- a/internal/model/table.go +++ b/internal/model/table.go @@ -69,6 +69,8 @@ func (t *Table) RemoveListener(l TableListener) { } if victim >= 0 { + t.mx.Lock() + defer t.mx.Unlock() t.listeners = append(t.listeners[:victim], t.listeners[victim+1:]...) } } @@ -303,6 +305,9 @@ func (t *Table) resourceMeta() ResourceMeta { } func (t *Table) fireTableChanged(data render.TableData) { + t.mx.RLock() + defer t.mx.RUnlock() + for _, l := range t.listeners { l.TableDataChanged(data) } diff --git a/internal/model/table_int_test.go b/internal/model/table_int_test.go index 3c71b534..78adfcf5 100644 --- a/internal/model/table_int_test.go +++ b/internal/model/table_int_test.go @@ -193,8 +193,8 @@ func (f testFactory) List(gvr, ns string, wait bool, sel labels.Selector) ([]run } return nil, nil } -func (f testFactory) ForResource(ns, gvr string) informers.GenericInformer { - return nil +func (f testFactory) ForResource(ns, gvr string) (informers.GenericInformer, error) { + return nil, nil } func (f testFactory) CanForResource(ns, gvr string, verbs []string) (informers.GenericInformer, error) { return nil, nil diff --git a/internal/model/table_test.go b/internal/model/table_test.go index 0c83f988..a144f684 100644 --- a/internal/model/table_test.go +++ b/internal/model/table_test.go @@ -100,8 +100,8 @@ func (f tableFactory) List(gvr, ns string, wait bool, sel labels.Selector) ([]ru } return nil, nil } -func (f tableFactory) ForResource(ns, gvr string) informers.GenericInformer { - return nil +func (f tableFactory) ForResource(ns, gvr string) (informers.GenericInformer, error) { + return nil, nil } func (f tableFactory) CanForResource(ns, gvr string, verbs []string) (informers.GenericInformer, error) { return nil, nil diff --git a/internal/render/popeye.go b/internal/render/popeye.go index 0330617b..abc5c652 100644 --- a/internal/render/popeye.go +++ b/internal/render/popeye.go @@ -41,10 +41,10 @@ func (Popeye) Header(ns string) Header { HeaderColumn{Name: "RESOURCE"}, HeaderColumn{Name: "SCORE%", Align: tview.AlignRight}, HeaderColumn{Name: "SCANNED", Align: tview.AlignRight}, - HeaderColumn{Name: "OK", Align: tview.AlignRight}, - HeaderColumn{Name: "INFO", Align: tview.AlignRight}, - HeaderColumn{Name: "WARNING", Align: tview.AlignRight}, HeaderColumn{Name: "ERROR", Align: tview.AlignRight}, + HeaderColumn{Name: "WARNING", Align: tview.AlignRight}, + HeaderColumn{Name: "INFO", Align: tview.AlignRight}, + HeaderColumn{Name: "OK", Align: tview.AlignRight}, } } @@ -60,10 +60,10 @@ func (Popeye) Render(o interface{}, ns string, r *Row) error { s.Title, strconv.Itoa(s.Tally.Score()), strconv.Itoa(s.Tally.OK+s.Tally.Info+s.Tally.Warning+s.Tally.Error), - strconv.Itoa(s.Tally.OK), - strconv.Itoa(s.Tally.Info), - strconv.Itoa(s.Tally.Warning), strconv.Itoa(s.Tally.Error), + strconv.Itoa(s.Tally.Warning), + strconv.Itoa(s.Tally.Info), + strconv.Itoa(s.Tally.OK), ) return nil } diff --git a/internal/view/app.go b/internal/view/app.go index 1d1dd83b..0cfc8c27 100644 --- a/internal/view/app.go +++ b/internal/view/app.go @@ -91,14 +91,13 @@ func (a *App) Init(version string, rate int) error { log.Debug().Msgf("CURRENT-NS %q -- %v", ns, err) if err != nil { log.Info().Msg("No namespace specified using cluster default namespace") - } else { - if err := a.Config.SetActiveNamespace(ns); err != nil { - log.Error().Err(err).Msgf("Fail to set active namespace to %q", ns) - } + } else if err = a.Config.SetActiveNamespace(ns); err != nil { + log.Error().Err(err).Msgf("Fail to set active namespace to %q", ns) } a.factory = watch.NewFactory(a.Conn()) - if !a.isValidNS(ns) { + ok, err := a.isValidNS(ns) + if !ok && err == nil { return fmt.Errorf("Invalid namespace %s", ns) } a.initFactory(ns) @@ -147,7 +146,9 @@ func (a *App) initSignals() { a.BailOut() return } - nukeK9sShell(a) + if err := nukeK9sShell(a); err != nil { + log.Error().Err(err).Msg("nuking k9s shell pod") + } }(sig) } @@ -315,30 +316,37 @@ func (a *App) switchNS(ns string) error { if ns == client.ClusterScope { ns = client.AllNamespaces } - if !a.isValidNS(ns) { + ok, err := a.isValidNS(ns) + if err != nil { + return err + } + if !ok { return fmt.Errorf("Invalid namespace %q", ns) } if err := a.Config.SetActiveNamespace(ns); err != nil { return fmt.Errorf("Unable to save active namespace in config") } - a.factory.SetActiveNS(ns) - return nil + return a.factory.SetActiveNS(ns) } -func (a *App) isValidNS(ns string) bool { +func (a *App) isValidNS(ns string) (bool, error) { if ns == client.AllNamespaces || ns == client.NamespaceAll { - return true + return true, nil } ctx, cancel := context.WithTimeout(context.Background(), client.CallTimeout) defer cancel() - _, err := a.Conn().DialOrDie().CoreV1().Namespaces().Get(ctx, ns, metav1.GetOptions{}) + dial, err := a.Conn().Dial() + if err != nil { + return false, err + } + _, err = dial.CoreV1().Namespaces().Get(ctx, ns, metav1.GetOptions{}) if err != nil { log.Warn().Err(err).Msgf("Validation failed for namespace: %q", ns) } - return true + return true, nil } func (a *App) switchCtx(name string, loadPods bool) error { @@ -388,7 +396,9 @@ func (a *App) BailOut() { } }() - nukeK9sShell(a) + if err := nukeK9sShell(a); err != nil { + log.Error().Err(err).Msgf("nuking k9s shell pod") + } a.factory.Terminate() a.App.BailOut() } diff --git a/internal/view/cm.go b/internal/view/cm.go index 5859d762..a6540a4d 100644 --- a/internal/view/cm.go +++ b/internal/view/cm.go @@ -27,7 +27,7 @@ func NewConfigMap(gvr client.GVR) ResourceViewer { func (s *ConfigMap) bindKeys(aa ui.KeyActions) { aa.Add(ui.KeyActions{ - ui.KeyR: ui.NewKeyAction("Referenced by", s.refCmd, true), + ui.KeyU: ui.NewKeyAction("UsedBy", s.refCmd, true), }) } diff --git a/internal/view/command.go b/internal/view/command.go index 3c4bd729..1b12b44f 100644 --- a/internal/view/command.go +++ b/internal/view/command.go @@ -38,7 +38,7 @@ func NewCommand(app *App) *Command { func (c *Command) Init() error { c.alias = dao.NewAlias(c.app.factory) if _, err := c.alias.Ensure(); err != nil { - return err + log.Error().Err(err).Msgf("command init failed!") } customViewers = loadCustomViewers() @@ -158,6 +158,9 @@ func (c *Command) run(cmd, path string, clearStack bool) error { } func (c *Command) defaultCmd() error { + if !c.app.Conn().ConnectionOK() { + return c.run("ctx", "", true) + } view := c.app.Config.ActiveView() if view == "" { return c.run("pod", "", true) diff --git a/internal/view/context.go b/internal/view/context.go index 802b70c3..5fe009d3 100644 --- a/internal/view/context.go +++ b/internal/view/context.go @@ -58,9 +58,6 @@ func useContext(app *App, name string) error { log.Error().Err(err).Msgf("Context switch failed") return err } - if err := app.switchCtx(name, true); err != nil { - return err - } - return nil + return app.switchCtx(name, true) } diff --git a/internal/view/exec.go b/internal/view/exec.go index aadaaa40..4ef8bdba 100644 --- a/internal/view/exec.go +++ b/internal/view/exec.go @@ -134,8 +134,14 @@ const ( ) func ssh(a *App, node string) error { - nukeK9sShell(a) - defer nukeK9sShell(a) + if err := nukeK9sShell(a); err != nil { + return err + } + defer func() { + if err := nukeK9sShell(a); err != nil { + log.Error().Err(err).Msgf("nuking k9s shell pod") + } + }() if err := launchShellPod(a, node); err != nil { return err } @@ -145,23 +151,27 @@ func ssh(a *App, node string) error { return nil } -func nukeK9sShell(a *App) { +func nukeK9sShell(a *App) error { cl := a.Config.K9s.CurrentCluster if !a.Config.K9s.Clusters[cl].FeatureGates.NodeShell { - return + return nil } ns := a.Config.K9s.ActiveCluster().ShellPod.Namespace ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) defer cancel() - err := a.Conn().DialOrDie().CoreV1().Pods(ns).Delete(ctx, k9sShellPodName(), metav1.DeleteOptions{}) - if kerrors.IsNotFound(err) { - return - } + dial, err := a.Conn().Dial() if err != nil { - log.Error().Err(err).Msgf("Fail to delete pod %s", k9sShell) + return err } + + err = dial.CoreV1().Pods(ns).Delete(ctx, k9sShellPodName(), metav1.DeleteOptions{}) + if kerrors.IsNotFound(err) { + return nil + } + + return err } func launchShellPod(a *App, node string) error { @@ -169,8 +179,13 @@ func launchShellPod(a *App, node string) error { spec := k9sShellPod(node, a.Config.K9s.ActiveCluster().ShellPod) ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) defer cancel() - dial := a.Conn().DialOrDie().CoreV1().Pods(ns) - if _, err := dial.Create(ctx, &spec, metav1.CreateOptions{}); err != nil { + + dial, err := a.Conn().Dial() + if err != nil { + return err + } + conn := dial.CoreV1().Pods(ns) + if _, err := conn.Create(ctx, &spec, metav1.CreateOptions{}); err != nil { return err } diff --git a/internal/view/node.go b/internal/view/node.go index f405c5bd..0aa0fc44 100644 --- a/internal/view/node.go +++ b/internal/view/node.go @@ -160,7 +160,12 @@ func (n *Node) yamlCmd(evt *tcell.EventKey) *tcell.EventKey { sel := n.GetTable().GetSelectedItem() gvr := n.GVR().GVR() - o, err := n.App().factory.Client().DynDialOrDie().Resource(gvr).Get(ctx, sel, metav1.GetOptions{}) + dial, err := n.App().factory.Client().DynDial() + if err != nil { + n.App().Flash().Err(err) + return nil + } + o, err := dial.Resource(gvr).Get(ctx, sel, metav1.GetOptions{}) if err != nil { n.App().Flash().Errf("Unable to get resource %q -- %s", n.GVR(), err) return nil diff --git a/internal/view/sa.go b/internal/view/sa.go index d059e887..4484c3c0 100644 --- a/internal/view/sa.go +++ b/internal/view/sa.go @@ -26,7 +26,7 @@ func NewServiceAccount(gvr client.GVR) ResourceViewer { func (s *ServiceAccount) bindKeys(aa ui.KeyActions) { aa.Add(ui.KeyActions{ - ui.KeyR: ui.NewKeyAction("Referenced by", s.refCmd, true), + ui.KeyU: ui.NewKeyAction("UsedBy", s.refCmd, true), }) } diff --git a/internal/view/secret.go b/internal/view/secret.go index c1604f57..1d34105d 100644 --- a/internal/view/secret.go +++ b/internal/view/secret.go @@ -30,7 +30,7 @@ func NewSecret(gvr client.GVR) ResourceViewer { func (s *Secret) bindKeys(aa ui.KeyActions) { aa.Add(ui.KeyActions{ ui.KeyX: ui.NewKeyAction("Decode", s.decodeCmd, true), - ui.KeyR: ui.NewKeyAction("Referenced by", s.refCmd, true), + ui.KeyU: ui.NewKeyAction("UsedBy", s.refCmd, true), }) } diff --git a/internal/watch/factory.go b/internal/watch/factory.go index 19b44842..a296700f 100644 --- a/internal/watch/factory.go +++ b/internal/watch/factory.go @@ -169,10 +169,12 @@ func (f *Factory) FactoryFor(ns string) di.DynamicSharedInformerFactory { } // SetActiveNS sets the active namespace. -func (f *Factory) SetActiveNS(ns string) { - if !f.isClusterWide() { - f.ensureFactory(ns) +func (f *Factory) SetActiveNS(ns string) error { + if f.isClusterWide() { + return nil } + _, err := f.ensureFactory(ns) + return err } func (f *Factory) isClusterWide() bool { @@ -193,42 +195,50 @@ func (f *Factory) CanForResource(ns, gvr string, verbs []string) (informers.Gene return nil, fmt.Errorf("%v access denied on resource %q:%q", verbs, ns, gvr) } - return f.ForResource(ns, gvr), nil + return f.ForResource(ns, gvr) } // ForResource returns an informer for a given resource. -func (f *Factory) ForResource(ns, gvr string) informers.GenericInformer { - fact := f.ensureFactory(ns) +func (f *Factory) ForResource(ns, gvr string) (informers.GenericInformer, error) { + fact, err := f.ensureFactory(ns) + if err != nil { + return nil, err + } inf := fact.ForResource(toGVR(gvr)) if inf == nil { log.Error().Err(fmt.Errorf("MEOW! No informer for %q:%q", ns, gvr)) - return inf + return inf, nil } f.mx.RLock() defer f.mx.RUnlock() fact.Start(f.stopChan) - return inf + return inf, nil } -func (f *Factory) ensureFactory(ns string) di.DynamicSharedInformerFactory { +func (f *Factory) ensureFactory(ns string) (di.DynamicSharedInformerFactory, error) { if client.IsClusterWide(ns) { ns = client.AllNamespaces } f.mx.Lock() defer f.mx.Unlock() if fac, ok := f.factories[ns]; ok { - return fac + return fac, nil + } + + dial, err := f.client.DynDial() + if err != nil { + return nil, err } f.factories[ns] = di.NewFilteredDynamicSharedInformerFactory( - f.client.DynDialOrDie(), + dial, defaultResync, ns, nil, ) - return f.factories[ns] + return f.factories[ns], nil } // AddForwarder registers a new portforward for a given container. diff --git a/internal/xray/container_test.go b/internal/xray/container_test.go index bf18164c..50b2db97 100644 --- a/internal/xray/container_test.go +++ b/internal/xray/container_test.go @@ -128,8 +128,8 @@ func (f testFactory) List(gvr, ns string, wait bool, sel labels.Selector) ([]run } return nil, nil } -func (f testFactory) ForResource(ns, gvr string) informers.GenericInformer { - return nil +func (f testFactory) ForResource(ns, gvr string) (informers.GenericInformer, error) { + return nil, nil } func (f testFactory) CanForResource(ns, gvr string, verbs []string) (informers.GenericInformer, error) { return nil, nil