refactor + added node view and sorters
parent
7542304adc
commit
6c3c9159de
|
|
@ -3,14 +3,14 @@ package k8s
|
|||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/rs/zerolog"
|
||||
authorizationv1 "k8s.io/api/authorization/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
// CanIAccess checks if user has access to a certain resource.
|
||||
func CanIAccess(ns, verb, name, resURL string) bool {
|
||||
func CanIAccess(cfg *Config, log zerolog.Logger, ns, verb, name, resURL string) bool {
|
||||
_, gr := schema.ParseResourceArg(strings.ToLower(resURL))
|
||||
sar := &authorizationv1.SelfSubjectAccessReview{
|
||||
Spec: authorizationv1.SelfSubjectAccessReviewSpec{
|
||||
|
|
@ -25,15 +25,21 @@ func CanIAccess(ns, verb, name, resURL string) bool {
|
|||
},
|
||||
}
|
||||
|
||||
auth, err := kubernetes.NewForConfig(conn.restConfigOrDie())
|
||||
rest, err := cfg.RESTConfig()
|
||||
if err != nil {
|
||||
log.Warn().Msgf("%s", err)
|
||||
log.Warn().Msgf("Access %s", err)
|
||||
return false
|
||||
}
|
||||
|
||||
auth, err := kubernetes.NewForConfig(rest)
|
||||
if err != nil {
|
||||
log.Warn().Msgf("Access %s", err)
|
||||
return false
|
||||
}
|
||||
|
||||
response, err := auth.AuthorizationV1().SelfSubjectAccessReviews().Create(sar)
|
||||
if err != nil {
|
||||
log.Warn().Msgf("%s", err)
|
||||
log.Warn().Msgf("Access %s", err)
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
package k8s
|
||||
|
||||
import (
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
clientcmd "k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
"k8s.io/kubernetes/pkg/kubectl/metricsutil"
|
||||
metricsapi "k8s.io/metrics/pkg/apis/metrics"
|
||||
versioned "k8s.io/metrics/pkg/client/clientset/versioned"
|
||||
)
|
||||
|
|
@ -15,10 +14,7 @@ import (
|
|||
// NA Not available
|
||||
const NA = "n/a"
|
||||
|
||||
var (
|
||||
conn = &apiServer{}
|
||||
supportedMetricsAPIVersions = []string{"v1beta1"}
|
||||
)
|
||||
var supportedMetricsAPIVersions = []string{"v1beta1"}
|
||||
|
||||
type (
|
||||
// APIGroup represents a K8s resource descriptor.
|
||||
|
|
@ -32,81 +28,125 @@ type (
|
|||
// Collection of empty interfaces.
|
||||
Collection []interface{}
|
||||
|
||||
// Res K8s api server calls.
|
||||
Res interface {
|
||||
// Cruder represent a crudable Kubernetes resource.
|
||||
Cruder interface {
|
||||
Get(ns string, name string) (interface{}, error)
|
||||
List(ns string) (Collection, error)
|
||||
Delete(ns string, name string) error
|
||||
}
|
||||
|
||||
// Connection represents a k8s api server connection.
|
||||
connection interface {
|
||||
configAccess() clientcmd.ConfigAccess
|
||||
restConfigOrDie() *restclient.Config
|
||||
apiConfigOrDie() clientcmdapi.Config
|
||||
dialOrDie() kubernetes.Interface
|
||||
dynDialOrDie() dynamic.Interface
|
||||
nsDialOrDie() dynamic.NamespaceableResourceInterface
|
||||
mxsDial() (*versioned.Clientset, error)
|
||||
heapsterDial() (*metricsutil.HeapsterMetricsClient, error)
|
||||
hasMetricsServer() bool
|
||||
// Connection represents a Kubenetes apiserver connection.
|
||||
Connection interface {
|
||||
Config() *Config
|
||||
DialOrDie() kubernetes.Interface
|
||||
SwitchContextOrDie(ctx string)
|
||||
NSDialOrDie() dynamic.NamespaceableResourceInterface
|
||||
RestConfigOrDie() *restclient.Config
|
||||
MXDial() (*versioned.Clientset, error)
|
||||
DynDialOrDie() dynamic.Interface
|
||||
HasMetrics() bool
|
||||
IsNamespaced(n string) bool
|
||||
SupportsResource(group string) bool
|
||||
}
|
||||
|
||||
apiServer struct {
|
||||
// APIClient represents a Kubernetes api client.
|
||||
APIClient struct {
|
||||
config *Config
|
||||
client kubernetes.Interface
|
||||
dClient dynamic.Interface
|
||||
nsClient dynamic.NamespaceableResourceInterface
|
||||
heapsterClient *metricsutil.HeapsterMetricsClient
|
||||
mxsClient *versioned.Clientset
|
||||
useMetricServer bool
|
||||
log zerolog.Logger
|
||||
}
|
||||
)
|
||||
|
||||
// InitConnectionOrDie initialize connection from command line args.
|
||||
// Checks for connectivity with the api server.
|
||||
func InitConnectionOrDie(config *Config) {
|
||||
conn = &apiServer{config: config}
|
||||
func InitConnectionOrDie(config *Config, logger zerolog.Logger) *APIClient {
|
||||
conn := APIClient{config: config, log: logger}
|
||||
conn.useMetricServer = conn.supportsMxServer()
|
||||
|
||||
return &conn
|
||||
}
|
||||
|
||||
func (a *apiServer) hasMetricsServer() bool {
|
||||
// IsNamespaced check on server if given resource is namespaced
|
||||
func (a *APIClient) IsNamespaced(res string) bool {
|
||||
list, _ := a.DialOrDie().Discovery().ServerPreferredResources()
|
||||
for _, l := range list {
|
||||
log.Debug().Msgf("GV %s", l.GroupVersion)
|
||||
for _, r := range l.APIResources {
|
||||
if r.Name == res {
|
||||
return r.Namespaced
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// SupportsResource checks for resource supported version against the server.
|
||||
func (a *APIClient) SupportsResource(group string) bool {
|
||||
list, _ := a.DialOrDie().Discovery().ServerPreferredResources()
|
||||
for _, l := range list {
|
||||
if l.GroupVersion == group {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Config return a kubernetes configuration.
|
||||
func (a *APIClient) Config() *Config {
|
||||
return a.config
|
||||
}
|
||||
|
||||
// HasMetrics returns true if the cluster supports metrics.
|
||||
func (a *APIClient) HasMetrics() bool {
|
||||
return a.useMetricServer
|
||||
}
|
||||
|
||||
// DialOrDie returns a handle to api server or die.
|
||||
func (a *apiServer) dialOrDie() kubernetes.Interface {
|
||||
func (a *APIClient) DialOrDie() kubernetes.Interface {
|
||||
if a.client != nil {
|
||||
return a.client
|
||||
}
|
||||
|
||||
var err error
|
||||
if a.client, err = kubernetes.NewForConfig(a.restConfigOrDie()); err != nil {
|
||||
panic(err)
|
||||
if a.client, err = kubernetes.NewForConfig(a.RestConfigOrDie()); err != nil {
|
||||
a.log.Panic().Err(err)
|
||||
}
|
||||
return a.client
|
||||
}
|
||||
|
||||
// DynDial returns a handle to the api server.
|
||||
func (a *apiServer) dynDialOrDie() dynamic.Interface {
|
||||
// RestConfigOrDie returns a rest api client.
|
||||
func (a *APIClient) RestConfigOrDie() *restclient.Config {
|
||||
cfg, err := a.config.RESTConfig()
|
||||
if err != nil {
|
||||
a.log.Panic().Err(err)
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
|
||||
// DynDialOrDie returns a handle to a dynamic interface.
|
||||
func (a *APIClient) DynDialOrDie() dynamic.Interface {
|
||||
if a.dClient != nil {
|
||||
return a.dClient
|
||||
}
|
||||
|
||||
var err error
|
||||
if a.dClient, err = dynamic.NewForConfig(a.restConfigOrDie()); err != nil {
|
||||
panic(err)
|
||||
if a.dClient, err = dynamic.NewForConfig(a.RestConfigOrDie()); err != nil {
|
||||
a.log.Panic().Err(err)
|
||||
}
|
||||
|
||||
return a.dClient
|
||||
}
|
||||
|
||||
func (a *apiServer) nsDialOrDie() dynamic.NamespaceableResourceInterface {
|
||||
// NSDialOrDie returns a handle to a namespaced resource.
|
||||
func (a *APIClient) NSDialOrDie() dynamic.NamespaceableResourceInterface {
|
||||
if a.nsClient != nil {
|
||||
return a.nsClient
|
||||
}
|
||||
|
||||
a.nsClient = a.dynDialOrDie().Resource(schema.GroupVersionResource{
|
||||
a.nsClient = a.DynDialOrDie().Resource(schema.GroupVersionResource{
|
||||
Group: "apiextensions.k8s.io",
|
||||
Version: "v1beta1",
|
||||
Resource: "customresourcedefinitions",
|
||||
|
|
@ -114,40 +154,21 @@ func (a *apiServer) nsDialOrDie() dynamic.NamespaceableResourceInterface {
|
|||
return a.nsClient
|
||||
}
|
||||
|
||||
func (a *apiServer) heapsterDial() (*metricsutil.HeapsterMetricsClient, error) {
|
||||
if a.heapsterClient != nil {
|
||||
return a.heapsterClient, nil
|
||||
}
|
||||
|
||||
a.heapsterClient = metricsutil.NewHeapsterMetricsClient(
|
||||
a.dialOrDie().CoreV1(),
|
||||
metricsutil.DefaultHeapsterNamespace,
|
||||
metricsutil.DefaultHeapsterScheme,
|
||||
metricsutil.DefaultHeapsterService,
|
||||
metricsutil.DefaultHeapsterPort,
|
||||
)
|
||||
return a.heapsterClient, nil
|
||||
}
|
||||
|
||||
func (a *apiServer) mxsDial() (*versioned.Clientset, error) {
|
||||
// MXDial returns a handle to the metrics server.
|
||||
func (a *APIClient) MXDial() (*versioned.Clientset, error) {
|
||||
if a.mxsClient != nil {
|
||||
return a.mxsClient, nil
|
||||
}
|
||||
|
||||
var err error
|
||||
a.mxsClient, err = versioned.NewForConfig(a.restConfigOrDie())
|
||||
if a.mxsClient, err = versioned.NewForConfig(a.RestConfigOrDie()); err != nil {
|
||||
a.log.Debug().Err(err)
|
||||
}
|
||||
return a.mxsClient, err
|
||||
}
|
||||
|
||||
func (a *apiServer) restConfigOrDie() *restclient.Config {
|
||||
cfg, err := a.config.RESTConfig()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
|
||||
func (a *apiServer) switchContextOrDie(ctx string) {
|
||||
// SwitchContextOrDie handles kubeconfig context switches.
|
||||
func (a *APIClient) SwitchContextOrDie(ctx string) {
|
||||
currentCtx, err := a.config.CurrentContextName()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
@ -162,13 +183,12 @@ func (a *apiServer) switchContextOrDie(ctx string) {
|
|||
}
|
||||
}
|
||||
|
||||
func (a *apiServer) reset() {
|
||||
a.client, a.dClient, a.nsClient = nil, nil, nil
|
||||
a.heapsterClient, a.mxsClient = nil, nil
|
||||
func (a *APIClient) reset() {
|
||||
a.client, a.dClient, a.nsClient, a.mxsClient = nil, nil, nil, nil
|
||||
}
|
||||
|
||||
func (a *apiServer) supportsMxServer() bool {
|
||||
apiGroups, err := a.dialOrDie().Discovery().ServerGroups()
|
||||
func (a *APIClient) supportsMxServer() bool {
|
||||
apiGroups, err := a.DialOrDie().Discovery().ServerGroups()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
|
@ -177,6 +197,7 @@ func (a *apiServer) supportsMxServer() bool {
|
|||
if discoveredAPIGroup.Name != metricsapi.GroupName {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, version := range discoveredAPIGroup.Versions {
|
||||
for _, supportedVersion := range supportedMetricsAPIVersions {
|
||||
if version.Version == supportedVersion {
|
||||
|
|
@ -185,5 +206,6 @@ func (a *apiServer) supportsMxServer() bool {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,26 @@
|
|||
package k8s
|
||||
|
||||
import "github.com/rs/zerolog/log"
|
||||
import (
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
// Cluster represents a Kubernetes cluster.
|
||||
type Cluster struct{}
|
||||
type Cluster struct {
|
||||
Connection
|
||||
|
||||
logger *zerolog.Logger
|
||||
}
|
||||
|
||||
// NewCluster instantiates a new cluster.
|
||||
func NewCluster() *Cluster {
|
||||
return &Cluster{}
|
||||
func NewCluster(c Connection, l *zerolog.Logger) *Cluster {
|
||||
return &Cluster{c, l}
|
||||
}
|
||||
|
||||
// Version returns the current cluster git version.
|
||||
func (c *Cluster) Version() (string, error) {
|
||||
rev, err := conn.dialOrDie().Discovery().ServerVersion()
|
||||
rev, err := c.DialOrDie().Discovery().ServerVersion()
|
||||
if err != nil {
|
||||
log.Warn().Msgf("%s", err)
|
||||
c.logger.Warn().Msgf("%s", err)
|
||||
return "", err
|
||||
}
|
||||
return rev.GitVersion, nil
|
||||
|
|
@ -22,9 +28,9 @@ func (c *Cluster) Version() (string, error) {
|
|||
|
||||
// ContextName returns the currently active context.
|
||||
func (c *Cluster) ContextName() string {
|
||||
ctx, err := conn.config.CurrentContextName()
|
||||
ctx, err := c.Config().CurrentContextName()
|
||||
if err != nil {
|
||||
log.Warn().Msgf("%s", err)
|
||||
c.logger.Warn().Msgf("%s", err)
|
||||
return "N/A"
|
||||
}
|
||||
return ctx
|
||||
|
|
@ -32,9 +38,9 @@ func (c *Cluster) ContextName() string {
|
|||
|
||||
// ClusterName return the currently active cluster name.
|
||||
func (c *Cluster) ClusterName() string {
|
||||
ctx, err := conn.config.CurrentClusterName()
|
||||
ctx, err := c.Config().CurrentClusterName()
|
||||
if err != nil {
|
||||
log.Warn().Msgf("%s", err)
|
||||
c.logger.Warn().Msgf("%s", err)
|
||||
return "N/A"
|
||||
}
|
||||
return ctx
|
||||
|
|
@ -42,9 +48,9 @@ func (c *Cluster) ClusterName() string {
|
|||
|
||||
// UserName returns the currently active user.
|
||||
func (c *Cluster) UserName() string {
|
||||
usr, err := conn.config.CurrentUserName()
|
||||
usr, err := c.Config().CurrentUserName()
|
||||
if err != nil {
|
||||
log.Warn().Msgf("%s", err)
|
||||
c.logger.Warn().Msgf("%s", err)
|
||||
return "N/A"
|
||||
}
|
||||
return usr
|
||||
|
|
|
|||
|
|
@ -5,28 +5,26 @@ import (
|
|||
)
|
||||
|
||||
// ClusterRole represents a Kubernetes ClusterRole
|
||||
type ClusterRole struct{}
|
||||
type ClusterRole struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewClusterRole returns a new ClusterRole.
|
||||
func NewClusterRole() Res {
|
||||
return &ClusterRole{}
|
||||
func NewClusterRole(c Connection) Cruder {
|
||||
return &ClusterRole{c}
|
||||
}
|
||||
|
||||
// Get a cluster role.
|
||||
func (*ClusterRole) Get(_, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().RbacV1().ClusterRoles().Get(n, opts)
|
||||
func (c *ClusterRole) Get(_, n string) (interface{}, error) {
|
||||
return c.DialOrDie().RbacV1().ClusterRoles().Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all ClusterRoles on a cluster.
|
||||
func (*ClusterRole) List(_ string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().RbacV1().ClusterRoles().List(opts)
|
||||
func (c *ClusterRole) List(_ string) (Collection, error) {
|
||||
rr, err := c.DialOrDie().RbacV1().ClusterRoles().List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -36,7 +34,6 @@ func (*ClusterRole) List(_ string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete a ClusterRole.
|
||||
func (*ClusterRole) Delete(_, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().RbacV1().ClusterRoles().Delete(n, &opts)
|
||||
func (c *ClusterRole) Delete(_, n string) error {
|
||||
return c.DialOrDie().RbacV1().ClusterRoles().Delete(n, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,28 +5,26 @@ import (
|
|||
)
|
||||
|
||||
// ClusterRoleBinding represents a Kubernetes ClusterRoleBinding
|
||||
type ClusterRoleBinding struct{}
|
||||
type ClusterRoleBinding struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewClusterRoleBinding returns a new ClusterRoleBinding.
|
||||
func NewClusterRoleBinding() Res {
|
||||
return &ClusterRoleBinding{}
|
||||
func NewClusterRoleBinding(c Connection) Cruder {
|
||||
return &ClusterRoleBinding{c}
|
||||
}
|
||||
|
||||
// Get a service.
|
||||
func (*ClusterRoleBinding) Get(_, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().RbacV1().ClusterRoleBindings().Get(n, opts)
|
||||
func (c *ClusterRoleBinding) Get(_, n string) (interface{}, error) {
|
||||
return c.DialOrDie().RbacV1().ClusterRoleBindings().Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all ClusterRoleBindings on a cluster.
|
||||
func (*ClusterRoleBinding) List(_ string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().RbacV1().ClusterRoleBindings().List(opts)
|
||||
func (c *ClusterRoleBinding) List(_ string) (Collection, error) {
|
||||
rr, err := c.DialOrDie().RbacV1().ClusterRoleBindings().List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -36,7 +34,6 @@ func (*ClusterRoleBinding) List(_ string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete a ClusterRoleBinding.
|
||||
func (*ClusterRoleBinding) Delete(_, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().RbacV1().ClusterRoleBindings().Delete(n, &opts)
|
||||
func (c *ClusterRoleBinding) Delete(_, n string) error {
|
||||
return c.DialOrDie().RbacV1().ClusterRoleBindings().Delete(n, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,28 +5,26 @@ import (
|
|||
)
|
||||
|
||||
// ConfigMap represents a Kubernetes ConfigMap
|
||||
type ConfigMap struct{}
|
||||
type ConfigMap struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewConfigMap returns a new ConfigMap.
|
||||
func NewConfigMap() Res {
|
||||
return &ConfigMap{}
|
||||
func NewConfigMap(c Connection) Cruder {
|
||||
return &ConfigMap{c}
|
||||
}
|
||||
|
||||
// Get a ConfigMap.
|
||||
func (c *ConfigMap) Get(ns, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().CoreV1().ConfigMaps(ns).Get(n, opts)
|
||||
return c.DialOrDie().CoreV1().ConfigMaps(ns).Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all ConfigMaps in a given namespace.
|
||||
func (c *ConfigMap) List(ns string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().CoreV1().ConfigMaps(ns).List(opts)
|
||||
rr, err := c.DialOrDie().CoreV1().ConfigMaps(ns).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -37,6 +35,5 @@ func (c *ConfigMap) List(ns string) (Collection, error) {
|
|||
|
||||
// Delete a ConfigMap.
|
||||
func (c *ConfigMap) Delete(ns, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().CoreV1().ConfigMaps(ns).Delete(n, &opts)
|
||||
return c.DialOrDie().CoreV1().ConfigMaps(ns).Delete(n, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,9 +14,6 @@ import (
|
|||
|
||||
const defaultNamespace = "default"
|
||||
|
||||
// KubeConfig represents kubeconfig settings.
|
||||
var KubeConfig *Config
|
||||
|
||||
// Config tracks a kubernetes configuration.
|
||||
type Config struct {
|
||||
flags *genericclioptions.ConfigFlags
|
||||
|
|
@ -28,8 +25,7 @@ type Config struct {
|
|||
|
||||
// NewConfig returns a new k8s config or an error if the flags are invalid.
|
||||
func NewConfig(f *genericclioptions.ConfigFlags) *Config {
|
||||
KubeConfig = &Config{flags: f}
|
||||
return KubeConfig
|
||||
return &Config{flags: f}
|
||||
}
|
||||
|
||||
// Flags returns configuration flags.
|
||||
|
|
@ -60,6 +56,7 @@ func (c *Config) CurrentContextName() (string, error) {
|
|||
if isSet(c.flags.Context) {
|
||||
return *c.flags.Context, nil
|
||||
}
|
||||
|
||||
cfg, err := c.RawConfig()
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
|
@ -82,11 +79,11 @@ func (c *Config) GetContext(n string) (*clientcmdapi.Context, error) {
|
|||
|
||||
// Contexts fetch all available contexts.
|
||||
func (c *Config) Contexts() (map[string]*clientcmdapi.Context, error) {
|
||||
var cc map[string]*clientcmdapi.Context
|
||||
cfg, err := c.RawConfig()
|
||||
if err != nil {
|
||||
return cc, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cfg.Contexts, nil
|
||||
}
|
||||
|
||||
|
|
@ -97,18 +94,18 @@ func (c *Config) DelContext(n string) error {
|
|||
return err
|
||||
}
|
||||
delete(cfg.Contexts, n)
|
||||
|
||||
return clientcmd.ModifyConfig(c.clientConfig.ConfigAccess(), cfg, true)
|
||||
}
|
||||
|
||||
// ContextNames fetch all available contexts.
|
||||
func (c *Config) ContextNames() ([]string, error) {
|
||||
var cc []string
|
||||
cfg, err := c.RawConfig()
|
||||
if err != nil {
|
||||
return cc, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc = make([]string, 0, len(cfg.Contexts))
|
||||
cc := make([]string, 0, len(cfg.Contexts))
|
||||
for n := range cfg.Contexts {
|
||||
cc = append(cc, n)
|
||||
}
|
||||
|
|
@ -121,6 +118,7 @@ func (c *Config) ClusterNameFromContext(ctx string) (string, error) {
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if ctx, ok := cfg.Contexts[ctx]; ok {
|
||||
return ctx.Cluster, nil
|
||||
}
|
||||
|
|
@ -137,32 +135,31 @@ func (c *Config) CurrentClusterName() (string, error) {
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
current := cfg.CurrentContext
|
||||
if isSet(c.flags.Context) {
|
||||
current = *c.flags.Context
|
||||
}
|
||||
|
||||
if ctx, ok := cfg.Contexts[current]; ok {
|
||||
return ctx.Cluster, nil
|
||||
}
|
||||
|
||||
return "", errors.New("unable to locate current cluster")
|
||||
}
|
||||
|
||||
// ClusterNames fetch all kubeconfig defined clusters.
|
||||
func (c *Config) ClusterNames() ([]string, error) {
|
||||
var cc []string
|
||||
if err := c.configFromFlags(); err != nil {
|
||||
return cc, err
|
||||
}
|
||||
|
||||
cfg, err := c.RawConfig()
|
||||
if err != nil {
|
||||
return cc, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc = make([]string, 0, len(cfg.Clusters))
|
||||
cc := make([]string, 0, len(cfg.Clusters))
|
||||
for name := range cfg.Clusters {
|
||||
cc = append(cc, name)
|
||||
}
|
||||
|
||||
return cc, nil
|
||||
}
|
||||
|
||||
|
|
@ -171,6 +168,7 @@ func (c *Config) CurrentUserName() (string, error) {
|
|||
if isSet(c.flags.Impersonate) {
|
||||
return *c.flags.Impersonate, nil
|
||||
}
|
||||
|
||||
if isSet(c.flags.AuthInfoName) {
|
||||
return *c.flags.AuthInfoName, nil
|
||||
}
|
||||
|
|
@ -187,6 +185,7 @@ func (c *Config) CurrentUserName() (string, error) {
|
|||
if ctx, ok := cfg.Contexts[current]; ok {
|
||||
return ctx.AuthInfo, nil
|
||||
}
|
||||
|
||||
return "", errors.New("unable to locate current cluster")
|
||||
}
|
||||
|
||||
|
|
@ -211,48 +210,39 @@ func (c *Config) CurrentNamespaceName() (string, error) {
|
|||
return ctx.Namespace, nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("No active namespace specified")
|
||||
}
|
||||
|
||||
// NamespaceNames fetch all available namespaces on current cluster.
|
||||
func (c *Config) NamespaceNames() ([]string, error) {
|
||||
ll, err := NewNamespace().List("")
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
func (c *Config) NamespaceNames(nns []v1.Namespace) []string {
|
||||
nn := make([]string, 0, len(nns))
|
||||
for _, ns := range nns {
|
||||
nn = append(nn, ns.Name)
|
||||
}
|
||||
nn := make([]string, 0, len(ll))
|
||||
for _, n := range ll {
|
||||
if ns, ok := n.(v1.Namespace); ok {
|
||||
nn = append(nn, ns.Name)
|
||||
}
|
||||
}
|
||||
return nn, nil
|
||||
|
||||
return nn
|
||||
}
|
||||
|
||||
// ConfigAccess return the current kubeconfig api server access configuration.
|
||||
func (c *Config) ConfigAccess() (clientcmd.ConfigAccess, error) {
|
||||
var acc clientcmd.ConfigAccess
|
||||
if err := c.configFromFlags(); err != nil {
|
||||
return acc, err
|
||||
}
|
||||
c.ensureConfig()
|
||||
return c.clientConfig.ConfigAccess(), nil
|
||||
}
|
||||
|
||||
// RawConfig fetch the current kubeconfig with no overrides.
|
||||
func (c *Config) RawConfig() (clientcmdapi.Config, error) {
|
||||
if c.rawConfig != nil {
|
||||
if c.rawConfig.CurrentContext != c.currentContext {
|
||||
log.Debug().Msgf("Context switch detected... %s vs %s", c.rawConfig.CurrentContext, c.currentContext)
|
||||
c.currentContext = c.rawConfig.CurrentContext
|
||||
c.reset()
|
||||
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 {
|
||||
if err := c.configFromFlags(); err != nil {
|
||||
return clientcmdapi.Config{}, err
|
||||
}
|
||||
log.Debug().Msg("Loading RawConfig...")
|
||||
c.ensureConfig()
|
||||
cfg, err := c.clientConfig.RawConfig()
|
||||
if err != nil {
|
||||
return cfg, err
|
||||
|
|
@ -260,36 +250,38 @@ func (c *Config) RawConfig() (clientcmdapi.Config, error) {
|
|||
c.rawConfig = &cfg
|
||||
c.currentContext = cfg.CurrentContext
|
||||
}
|
||||
|
||||
return *c.rawConfig, nil
|
||||
}
|
||||
|
||||
// RESTConfig fetch the current REST api service connection.
|
||||
func (c *Config) RESTConfig() (*restclient.Config, error) {
|
||||
var err error
|
||||
if c.restConfig == nil {
|
||||
if err = c.configFromFlags(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.restConfig, err = c.flags.ToRESTConfig()
|
||||
if err != nil {
|
||||
return c.restConfig, err
|
||||
}
|
||||
log.Debug().Msgf("Connecting to API Server %s", c.restConfig.Host)
|
||||
if c.restConfig != nil {
|
||||
return c.restConfig, nil
|
||||
}
|
||||
|
||||
var err error
|
||||
if c.restConfig, err = c.flags.ToRESTConfig(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Debug().Msgf("Connecting to API Server %s", c.restConfig.Host)
|
||||
|
||||
return c.restConfig, nil
|
||||
}
|
||||
|
||||
func (c *Config) ensureConfig() {
|
||||
if c.clientConfig != nil {
|
||||
return
|
||||
}
|
||||
|
||||
log.Debug().Msg("Loading raw config from flags...")
|
||||
c.clientConfig = c.flags.ToRawKubeConfigLoader()
|
||||
return
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Helpers...
|
||||
|
||||
func (c *Config) configFromFlags() error {
|
||||
if c.clientConfig == nil {
|
||||
log.Debug().Msg("Loading raw config from flags...")
|
||||
c.clientConfig = c.flags.ToRawKubeConfigLoader()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isSet(s *string) bool {
|
||||
return s != nil && len(*s) != 0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import (
|
|||
"github.com/derailed/k9s/internal/k8s"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/stretchr/testify/assert"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||
)
|
||||
|
||||
|
|
@ -228,3 +230,22 @@ func TestConfigBadConfig(t *testing.T) {
|
|||
_, err := cfg.RESTConfig()
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestNamespaceNames(t *testing.T) {
|
||||
kubeConfig := "./assets/config"
|
||||
|
||||
flags := genericclioptions.ConfigFlags{
|
||||
KubeConfig: &kubeConfig,
|
||||
}
|
||||
|
||||
cfg := k8s.NewConfig(&flags)
|
||||
|
||||
nn := []v1.Namespace{
|
||||
{ObjectMeta: metav1.ObjectMeta{Name: "ns1"}},
|
||||
{ObjectMeta: metav1.ObjectMeta{Name: "ns2"}},
|
||||
}
|
||||
|
||||
nns := cfg.NamespaceNames(nn)
|
||||
assert.Equal(t, 2, len(nns))
|
||||
assert.Equal(t, []string{"ns1", "ns2"}, nns)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import (
|
|||
|
||||
// ContextRes represents a Kubernetes clusters configurations.
|
||||
type ContextRes interface {
|
||||
Res
|
||||
Cruder
|
||||
Switch(n string) error
|
||||
}
|
||||
|
||||
|
|
@ -17,11 +17,17 @@ type ContextRes interface {
|
|||
type NamedContext struct {
|
||||
Name string
|
||||
Context *api.Context
|
||||
config *Config
|
||||
}
|
||||
|
||||
// NewNamedContext returns a new named context.
|
||||
func NewNamedContext(c *Config, n string, ctx *api.Context) *NamedContext {
|
||||
return &NamedContext{Name: n, Context: ctx, config: c}
|
||||
}
|
||||
|
||||
// MustCurrentContextName return the active context name.
|
||||
func (c *NamedContext) MustCurrentContextName() string {
|
||||
cl, err := conn.config.CurrentContextName()
|
||||
cl, err := c.config.CurrentContextName()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
@ -29,16 +35,18 @@ func (c *NamedContext) MustCurrentContextName() string {
|
|||
}
|
||||
|
||||
// Context represents a Kubernetes Context.
|
||||
type Context struct{}
|
||||
type Context struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewContext returns a new Context.
|
||||
func NewContext() Res {
|
||||
return &Context{}
|
||||
func NewContext(c Connection) Cruder {
|
||||
return &Context{c}
|
||||
}
|
||||
|
||||
// Get a Context.
|
||||
func (*Context) Get(_, n string) (interface{}, error) {
|
||||
ctx, err := conn.config.GetContext(n)
|
||||
func (c *Context) Get(_, n string) (interface{}, error) {
|
||||
ctx, err := c.Config().GetContext(n)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -46,43 +54,45 @@ func (*Context) Get(_, n string) (interface{}, error) {
|
|||
}
|
||||
|
||||
// List all Contexts on the current cluster.
|
||||
func (*Context) List(string) (Collection, error) {
|
||||
ctxs, err := conn.config.Contexts()
|
||||
func (c *Context) List(string) (Collection, error) {
|
||||
ctxs, err := c.Config().Contexts()
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
cc := make([]interface{}, 0, len(ctxs))
|
||||
for k, v := range ctxs {
|
||||
cc = append(cc, &NamedContext{k, v})
|
||||
cc = append(cc, NewNamedContext(c.Config(), k, v))
|
||||
}
|
||||
|
||||
return cc, nil
|
||||
}
|
||||
|
||||
// Delete a Context.
|
||||
func (*Context) Delete(_, n string) error {
|
||||
ctx, err := conn.config.CurrentContextName()
|
||||
func (c *Context) Delete(_, n string) error {
|
||||
ctx, err := c.Config().CurrentContextName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ctx == n {
|
||||
return fmt.Errorf("trying to delete your current context %s", n)
|
||||
}
|
||||
return conn.config.DelContext(n)
|
||||
return c.Config().DelContext(n)
|
||||
}
|
||||
|
||||
// Switch to another context.
|
||||
func (*Context) Switch(n string) error {
|
||||
conn.switchContextOrDie(n)
|
||||
func (c *Context) Switch(ctx string) error {
|
||||
c.SwitchContextOrDie(ctx)
|
||||
return nil
|
||||
}
|
||||
|
||||
// KubeUpdate modifies kubeconfig default context.
|
||||
func (c *Context) KubeUpdate(n string) error {
|
||||
c.Switch(n)
|
||||
acc := clientcmd.NewDefaultPathOptions()
|
||||
config, err := conn.config.RawConfig()
|
||||
config, err := c.Config().RawConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return clientcmd.ModifyConfig(acc, config, true)
|
||||
c.Switch(n)
|
||||
return clientcmd.ModifyConfig(
|
||||
clientcmd.NewDefaultPathOptions(), config, true,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,28 +5,26 @@ import (
|
|||
)
|
||||
|
||||
// CRD represents a Kubernetes CRD
|
||||
type CRD struct{}
|
||||
type CRD struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewCRD returns a new CRD.
|
||||
func NewCRD() Res {
|
||||
return &CRD{}
|
||||
func NewCRD(c Connection) Cruder {
|
||||
return &CRD{c}
|
||||
}
|
||||
|
||||
// Get a CRD.
|
||||
func (*CRD) Get(_, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.nsDialOrDie().Get(n, opts)
|
||||
func (c *CRD) Get(_, n string) (interface{}, error) {
|
||||
return c.NSDialOrDie().Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all CRDs in a given namespace.
|
||||
func (*CRD) List(string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.nsDialOrDie().List(opts)
|
||||
func (c *CRD) List(string) (Collection, error) {
|
||||
rr, err := c.NSDialOrDie().List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -36,7 +34,6 @@ func (*CRD) List(string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete a CRD.
|
||||
func (*CRD) Delete(_, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.nsDialOrDie().Delete(n, &opts)
|
||||
func (c *CRD) Delete(_, n string) error {
|
||||
return c.NSDialOrDie().Delete(n, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,28 +10,26 @@ import (
|
|||
const maxJobNameSize = 42
|
||||
|
||||
// CronJob represents a Kubernetes CronJob.
|
||||
type CronJob struct{}
|
||||
type CronJob struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewCronJob returns a new CronJob.
|
||||
func NewCronJob() Res {
|
||||
return &CronJob{}
|
||||
func NewCronJob(c Connection) Cruder {
|
||||
return &CronJob{c}
|
||||
}
|
||||
|
||||
// Get a CronJob.
|
||||
func (c *CronJob) Get(ns, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().BatchV1beta1().CronJobs(ns).Get(n, opts)
|
||||
return c.DialOrDie().BatchV1beta1().CronJobs(ns).Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all CronJobs in a given namespace.
|
||||
func (c *CronJob) List(ns string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().BatchV1beta1().CronJobs(ns).List(opts)
|
||||
rr, err := c.DialOrDie().BatchV1beta1().CronJobs(ns).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -42,22 +40,20 @@ func (c *CronJob) List(ns string) (Collection, error) {
|
|||
|
||||
// Delete a CronJob.
|
||||
func (c *CronJob) Delete(ns, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().BatchV1beta1().CronJobs(ns).Delete(n, &opts)
|
||||
return c.DialOrDie().BatchV1beta1().CronJobs(ns).Delete(n, nil)
|
||||
}
|
||||
|
||||
// Run the job associated with this cronjob.
|
||||
func (c *CronJob) Run(ns, n string) error {
|
||||
i, err := c.Get(ns, n)
|
||||
cj, err := c.Get(ns, n)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cronJob := i.(*batchv1beta1.CronJob)
|
||||
cronJob := cj.(*batchv1beta1.CronJob)
|
||||
|
||||
var jobName = cronJob.Name
|
||||
if len(cronJob.Name) >= maxJobNameSize {
|
||||
jobName = cronJob.Name[0:41]
|
||||
jobName = cronJob.Name[0:maxJobNameSize]
|
||||
}
|
||||
|
||||
job := &batchv1.Job{
|
||||
|
|
@ -68,6 +64,7 @@ func (c *CronJob) Run(ns, n string) error {
|
|||
},
|
||||
Spec: cronJob.Spec.JobTemplate.Spec,
|
||||
}
|
||||
_, err = conn.dialOrDie().BatchV1().Jobs(ns).Create(job)
|
||||
|
||||
_, err = c.DialOrDie().BatchV1().Jobs(ns).Create(job)
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,28 +5,26 @@ import (
|
|||
)
|
||||
|
||||
// Deployment represents a Kubernetes Deployment.
|
||||
type Deployment struct{}
|
||||
type Deployment struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewDeployment returns a new Deployment.
|
||||
func NewDeployment() Res {
|
||||
return &Deployment{}
|
||||
func NewDeployment(c Connection) Cruder {
|
||||
return &Deployment{c}
|
||||
}
|
||||
|
||||
// Get a deployment.
|
||||
func (*Deployment) Get(ns, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().Apps().Deployments(ns).Get(n, opts)
|
||||
func (d *Deployment) Get(ns, n string) (interface{}, error) {
|
||||
return d.DialOrDie().Apps().Deployments(ns).Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all Deployments in a given namespace.
|
||||
func (*Deployment) List(ns string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().Apps().Deployments(ns).List(opts)
|
||||
func (d *Deployment) List(ns string) (Collection, error) {
|
||||
rr, err := d.DialOrDie().Apps().Deployments(ns).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -36,7 +34,6 @@ func (*Deployment) List(ns string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete a Deployment.
|
||||
func (*Deployment) Delete(ns, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().Apps().Deployments(ns).Delete(n, &opts)
|
||||
func (d *Deployment) Delete(ns, n string) error {
|
||||
return d.DialOrDie().Apps().Deployments(ns).Delete(n, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,28 +5,26 @@ import (
|
|||
)
|
||||
|
||||
// DaemonSet represents a Kubernetes DaemonSet
|
||||
type DaemonSet struct{}
|
||||
type DaemonSet struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewDaemonSet returns a new DaemonSet.
|
||||
func NewDaemonSet() Res {
|
||||
return &DaemonSet{}
|
||||
func NewDaemonSet(c Connection) Cruder {
|
||||
return &DaemonSet{c}
|
||||
}
|
||||
|
||||
// Get a DaemonSet.
|
||||
func (*DaemonSet) Get(ns, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().ExtensionsV1beta1().DaemonSets(ns).Get(n, opts)
|
||||
func (d *DaemonSet) Get(ns, n string) (interface{}, error) {
|
||||
return d.DialOrDie().ExtensionsV1beta1().DaemonSets(ns).Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all DaemonSets in a given namespace.
|
||||
func (*DaemonSet) List(ns string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().ExtensionsV1beta1().DaemonSets(ns).List(opts)
|
||||
func (d *DaemonSet) List(ns string) (Collection, error) {
|
||||
rr, err := d.DialOrDie().ExtensionsV1beta1().DaemonSets(ns).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -36,7 +34,6 @@ func (*DaemonSet) List(ns string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete a DaemonSet.
|
||||
func (*DaemonSet) Delete(ns, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().ExtensionsV1beta1().DaemonSets(ns).Delete(n, &opts)
|
||||
func (d *DaemonSet) Delete(ns, n string) error {
|
||||
return d.DialOrDie().ExtensionsV1beta1().DaemonSets(ns).Delete(n, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,28 +5,26 @@ import (
|
|||
)
|
||||
|
||||
// Endpoints represents a Kubernetes Endpoints.
|
||||
type Endpoints struct{}
|
||||
type Endpoints struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewEndpoints returns a new Endpoints.
|
||||
func NewEndpoints() Res {
|
||||
return &Endpoints{}
|
||||
func NewEndpoints(c Connection) Cruder {
|
||||
return &Endpoints{c}
|
||||
}
|
||||
|
||||
// Get a Endpoint.
|
||||
func (*Endpoints) Get(ns, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().CoreV1().Endpoints(ns).Get(n, opts)
|
||||
func (e *Endpoints) Get(ns, n string) (interface{}, error) {
|
||||
return e.DialOrDie().CoreV1().Endpoints(ns).Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all Endpoints in a given namespace.
|
||||
func (*Endpoints) List(ns string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().CoreV1().Endpoints(ns).List(opts)
|
||||
func (e *Endpoints) List(ns string) (Collection, error) {
|
||||
rr, err := e.DialOrDie().CoreV1().Endpoints(ns).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -36,7 +34,6 @@ func (*Endpoints) List(ns string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete a Endpoint.
|
||||
func (*Endpoints) Delete(ns, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().CoreV1().Endpoints(ns).Delete(n, &opts)
|
||||
func (e *Endpoints) Delete(ns, n string) error {
|
||||
return e.DialOrDie().CoreV1().Endpoints(ns).Delete(n, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,28 +5,26 @@ import (
|
|||
)
|
||||
|
||||
// Event represents a Kubernetes Event.
|
||||
type Event struct{}
|
||||
type Event struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewEvent returns a new Event.
|
||||
func NewEvent() Res {
|
||||
return &Event{}
|
||||
func NewEvent(c Connection) Cruder {
|
||||
return &Event{c}
|
||||
}
|
||||
|
||||
// Get a Event.
|
||||
func (*Event) Get(ns, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().CoreV1().Events(ns).Get(n, opts)
|
||||
func (e *Event) Get(ns, n string) (interface{}, error) {
|
||||
return e.DialOrDie().CoreV1().Events(ns).Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all Events in a given namespace.
|
||||
func (*Event) List(ns string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().CoreV1().Events(ns).List(opts)
|
||||
func (e *Event) List(ns string) (Collection, error) {
|
||||
rr, err := e.DialOrDie().CoreV1().Events(ns).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -36,7 +34,6 @@ func (*Event) List(ns string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete an Event.
|
||||
func (*Event) Delete(ns, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().CoreV1().Events(ns).Delete(n, &opts)
|
||||
func (e *Event) Delete(ns, n string) error {
|
||||
return e.DialOrDie().CoreV1().Events(ns).Delete(n, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
package k8s
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
const megaByte = 1024 * 1024
|
||||
|
||||
func asMi(v int64) float64 {
|
||||
return float64(v) / megaByte
|
||||
}
|
||||
|
||||
func toPerc(v1, v2 float64) float64 {
|
||||
if v2 == 0 {
|
||||
return 0
|
||||
}
|
||||
return math.Round((v1 / v2) * 100)
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package k8s
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestToPerc(t *testing.T) {
|
||||
uu := []struct {
|
||||
v1, v2, e float64
|
||||
}{
|
||||
{0, 0, 0},
|
||||
{100, 200, 50},
|
||||
{200, 100, 200},
|
||||
}
|
||||
|
||||
for _, u := range uu {
|
||||
assert.Equal(t, u.e, toPerc(u.v1, u.v2))
|
||||
}
|
||||
}
|
||||
|
||||
func TestAsMi(t *testing.T) {
|
||||
uu := []struct {
|
||||
v int64
|
||||
e float64
|
||||
}{
|
||||
{0, 0},
|
||||
{2 * megaByte, 2},
|
||||
{10 * megaByte, 10},
|
||||
}
|
||||
|
||||
for _, u := range uu {
|
||||
assert.Equal(t, u.e, asMi(u.v))
|
||||
}
|
||||
}
|
||||
|
|
@ -5,38 +5,37 @@ import (
|
|||
)
|
||||
|
||||
// HPA represents am HorizontalPodAutoscaler.
|
||||
type HPA struct{}
|
||||
type HPA struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewHPA returns a new HPA.
|
||||
func NewHPA() Res {
|
||||
return &HPA{}
|
||||
func NewHPA(c Connection) Cruder {
|
||||
return &HPA{c}
|
||||
}
|
||||
|
||||
// Get a HPA.
|
||||
func (*HPA) Get(ns, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().AutoscalingV2beta2().HorizontalPodAutoscalers(ns).Get(n, opts)
|
||||
func (h *HPA) Get(ns, n string) (interface{}, error) {
|
||||
return h.DialOrDie().AutoscalingV2beta2().HorizontalPodAutoscalers(ns).Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all HPAs in a given namespace.
|
||||
func (*HPA) List(ns string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().AutoscalingV2beta2().HorizontalPodAutoscalers(ns).List(opts)
|
||||
func (h *HPA) List(ns string) (Collection, error) {
|
||||
rr, err := h.DialOrDie().AutoscalingV2beta2().HorizontalPodAutoscalers(ns).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
}
|
||||
|
||||
return cc, nil
|
||||
}
|
||||
|
||||
// Delete a HPA.
|
||||
func (*HPA) Delete(ns, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().AutoscalingV2beta2().HorizontalPodAutoscalers(ns).Delete(n, &opts)
|
||||
func (h *HPA) Delete(ns, n string) error {
|
||||
if h.SupportsResource("autoscaling/v2beta1") {
|
||||
return h.DialOrDie().AutoscalingV2beta1().HorizontalPodAutoscalers(ns).Delete(n, nil)
|
||||
}
|
||||
return h.DialOrDie().AutoscalingV2beta2().HorizontalPodAutoscalers(ns).Delete(n, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,28 +5,26 @@ import (
|
|||
)
|
||||
|
||||
// Ingress represents a Kubernetes Ingress.
|
||||
type Ingress struct{}
|
||||
type Ingress struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewIngress returns a new Ingress.
|
||||
func NewIngress() Res {
|
||||
return &Ingress{}
|
||||
func NewIngress(c Connection) Cruder {
|
||||
return &Ingress{c}
|
||||
}
|
||||
|
||||
// Get a Ingress.
|
||||
func (*Ingress) Get(ns, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().ExtensionsV1beta1().Ingresses(ns).Get(n, opts)
|
||||
func (i *Ingress) Get(ns, n string) (interface{}, error) {
|
||||
return i.DialOrDie().ExtensionsV1beta1().Ingresses(ns).Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all Ingresss in a given namespace.
|
||||
func (*Ingress) List(ns string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().ExtensionsV1beta1().Ingresses(ns).List(opts)
|
||||
func (i *Ingress) List(ns string) (Collection, error) {
|
||||
rr, err := i.DialOrDie().ExtensionsV1beta1().Ingresses(ns).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -36,7 +34,6 @@ func (*Ingress) List(ns string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete a Ingress.
|
||||
func (*Ingress) Delete(ns, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().ExtensionsV1beta1().Ingresses(ns).Delete(n, &opts)
|
||||
func (i *Ingress) Delete(ns, n string) error {
|
||||
return i.DialOrDie().ExtensionsV1beta1().Ingresses(ns).Delete(n, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,35 +4,40 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// Job represents a Kubernetes Job.
|
||||
type Job struct{}
|
||||
type (
|
||||
// Job represents a Kubernetes Job.
|
||||
Job struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// Loggable represents a K8s resource that has containers and can be logged.
|
||||
Loggable interface {
|
||||
Containers(ns, n string, includeInit bool) ([]string, error)
|
||||
Logs(ns, n, co string, lines int64, previous bool) *restclient.Request
|
||||
}
|
||||
)
|
||||
|
||||
// NewJob returns a new Job.
|
||||
func NewJob() Res {
|
||||
return &Job{}
|
||||
func NewJob(c Connection) Cruder {
|
||||
return &Job{c}
|
||||
}
|
||||
|
||||
// Get a Job.
|
||||
func (*Job) Get(ns, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().BatchV1().Jobs(ns).Get(n, opts)
|
||||
func (j *Job) Get(ns, n string) (interface{}, error) {
|
||||
return j.DialOrDie().BatchV1().Jobs(ns).Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all Jobs in a given namespace.
|
||||
func (*Job) List(ns string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().BatchV1().Jobs(ns).List(opts)
|
||||
func (j *Job) List(ns string) (Collection, error) {
|
||||
rr, err := j.DialOrDie().BatchV1().Jobs(ns).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -42,9 +47,8 @@ func (*Job) List(ns string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete a Job.
|
||||
func (*Job) Delete(ns, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().BatchV1().Jobs(ns).Delete(n, &opts)
|
||||
func (j *Job) Delete(ns, n string) error {
|
||||
return j.DialOrDie().BatchV1().Jobs(ns).Delete(n, nil)
|
||||
}
|
||||
|
||||
// Containers returns all container names on job.
|
||||
|
|
@ -53,8 +57,7 @@ func (j *Job) Containers(ns, n string, includeInit bool) ([]string, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Debug().Msgf("Containers found assoc pod %v", pod)
|
||||
return NewPod().(Loggable).Containers(ns, pod, includeInit)
|
||||
return NewPod(j).(Loggable).Containers(ns, pod, includeInit)
|
||||
}
|
||||
|
||||
// Logs fetch container logs for a given job and container.
|
||||
|
|
@ -63,16 +66,15 @@ func (j *Job) Logs(ns, n, co string, lines int64, prev bool) *restclient.Request
|
|||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return NewPod().(Loggable).Logs(ns, pod, co, lines, prev)
|
||||
return NewPod(j).(Loggable).Logs(ns, pod, co, lines, prev)
|
||||
}
|
||||
|
||||
// Events retrieved jobs events.
|
||||
func (*Job) Events(ns, n string) (*v1.EventList, error) {
|
||||
e := conn.dialOrDie().Core().Events(ns)
|
||||
sel := e.GetFieldSelector(&n, &ns, nil, nil)
|
||||
opts := metav1.ListOptions{FieldSelector: sel.String()}
|
||||
ee, err := e.List(opts)
|
||||
return ee, err
|
||||
func (j *Job) Events(ns, n string) (*v1.EventList, error) {
|
||||
e := j.DialOrDie().Core().Events(ns)
|
||||
return e.List(metav1.ListOptions{
|
||||
FieldSelector: e.GetFieldSelector(&n, &ns, nil, nil).String(),
|
||||
})
|
||||
}
|
||||
|
||||
func (j *Job) assocPod(ns, n string) (string, error) {
|
||||
|
|
|
|||
|
|
@ -14,12 +14,17 @@ import (
|
|||
"k8s.io/client-go/restmapper"
|
||||
)
|
||||
|
||||
// RestMapping holds k8s resource mapping
|
||||
// BOZO!! Has to be a better way...
|
||||
var RestMapping = &RestMapper{}
|
||||
var (
|
||||
// RestMapping holds k8s resource mapping
|
||||
// BOZO!! Has to be a better way...
|
||||
RestMapping = &RestMapper{}
|
||||
toFileName = regexp.MustCompile(`[^(\w/\.)]`)
|
||||
)
|
||||
|
||||
// RestMapper map resource to REST mapping ie kind, group, version.
|
||||
type RestMapper struct{}
|
||||
type RestMapper struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// Find a mapping given a resource name.
|
||||
func (*RestMapper) Find(res string) (*meta.RESTMapping, error) {
|
||||
|
|
@ -30,8 +35,8 @@ func (*RestMapper) Find(res string) (*meta.RESTMapping, error) {
|
|||
}
|
||||
|
||||
// ToRESTMapper map resources to kind, and map kind and version to interfaces for manipulating K8s objects.
|
||||
func (*RestMapper) ToRESTMapper() (meta.RESTMapper, error) {
|
||||
rc := conn.restConfigOrDie()
|
||||
func (r *RestMapper) ToRESTMapper() (meta.RESTMapper, error) {
|
||||
rc := r.RestConfigOrDie()
|
||||
|
||||
httpCacheDir := filepath.Join(mustHomeDir(), ".kube", "http-cache")
|
||||
discCacheDir := filepath.Join(mustHomeDir(), ".kube", "cache", "discovery", toHostDir(rc.Host))
|
||||
|
|
@ -45,11 +50,8 @@ func (*RestMapper) ToRESTMapper() (meta.RESTMapper, error) {
|
|||
return expander, nil
|
||||
}
|
||||
|
||||
var toFileName = regexp.MustCompile(`[^(\w/\.)]`)
|
||||
|
||||
func toHostDir(host string) string {
|
||||
h := strings.Replace(strings.Replace(host, "https://", "", 1), "http://", "", 1)
|
||||
// now do a simple collapse of non-AZ09 characters. Collisions are possible but unlikely. Even if we do collide the problem is short lived
|
||||
return toFileName.ReplaceAllString(h, "_")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,218 +1,145 @@
|
|||
package k8s
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"path"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
metricsapi "k8s.io/metrics/pkg/apis/metrics"
|
||||
metricsV1beta1api "k8s.io/metrics/pkg/apis/metrics/v1beta1"
|
||||
mv1beta1 "k8s.io/metrics/pkg/apis/metrics/v1beta1"
|
||||
)
|
||||
|
||||
type (
|
||||
// MetricsServer serves cluster metrics for nodes and pods.
|
||||
MetricsServer struct{}
|
||||
|
||||
// Metric tracks resource metrics.
|
||||
Metric struct {
|
||||
CPU string
|
||||
Mem string
|
||||
AvailCPU string
|
||||
AvailMem string
|
||||
MetricsServer struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NodeMetrics describes raw node metrics.
|
||||
NodeMetrics struct {
|
||||
CurrentCPU int64
|
||||
CurrentMEM float64
|
||||
AvailCPU int64
|
||||
AvailMEM float64
|
||||
TotalCPU int64
|
||||
TotalMEM float64
|
||||
}
|
||||
|
||||
// PodMetrics represent an aggregation of all pod containers metrics.
|
||||
PodMetrics struct {
|
||||
CurrentCPU int64
|
||||
CurrentMEM float64
|
||||
}
|
||||
|
||||
// ClusterMetrics summarizes total node metrics as percentages.
|
||||
ClusterMetrics struct {
|
||||
PercCPU float64
|
||||
PercMEM float64
|
||||
}
|
||||
|
||||
// NodesMetrics tracks usage metrics per nodes.
|
||||
NodesMetrics map[string]NodeMetrics
|
||||
|
||||
// PodsMetrics tracks usage metrics per pods.
|
||||
PodsMetrics map[string]PodMetrics
|
||||
)
|
||||
|
||||
// NewMetricsServer return a metric server instance.
|
||||
func NewMetricsServer() *MetricsServer {
|
||||
return &MetricsServer{}
|
||||
func NewMetricsServer(c Connection) *MetricsServer {
|
||||
return &MetricsServer{c}
|
||||
}
|
||||
|
||||
// NodeMetrics retrieves all nodes metrics
|
||||
func (m *MetricsServer) NodeMetrics() (Metric, error) {
|
||||
var mx Metric
|
||||
|
||||
opts := metav1.ListOptions{}
|
||||
nn, err := conn.dialOrDie().CoreV1().Nodes().List(opts)
|
||||
if err != nil {
|
||||
log.Warn().Msgf("%s", err)
|
||||
return mx, err
|
||||
}
|
||||
|
||||
nods := make([]string, len(nn.Items))
|
||||
var maxCPU, maxMem float64
|
||||
for i, n := range nn.Items {
|
||||
nods[i] = n.Name
|
||||
c := n.Status.Allocatable["cpu"]
|
||||
maxCPU += float64(c.MilliValue())
|
||||
m := n.Status.Allocatable["memory"]
|
||||
maxMem += float64(m.Value() / (1024 * 1024))
|
||||
}
|
||||
|
||||
mm, err := m.getNodeMetrics()
|
||||
if err != nil {
|
||||
log.Warn().Msgf("%s", err)
|
||||
return mx, err
|
||||
}
|
||||
|
||||
var cpu, mem float64
|
||||
for _, n := range nods {
|
||||
for _, m := range mm.Items {
|
||||
if m.Name == n {
|
||||
cpu += float64(m.Usage.Cpu().MilliValue())
|
||||
mem += float64(m.Usage.Memory().Value() / (1024 * 1024))
|
||||
}
|
||||
}
|
||||
}
|
||||
mx = Metric{
|
||||
CPU: fmt.Sprintf("%0.f%%", math.Round((cpu/maxCPU)*100)),
|
||||
Mem: fmt.Sprintf("%0.f%%", math.Round((mem/maxMem)*100)),
|
||||
}
|
||||
|
||||
return mx, nil
|
||||
}
|
||||
|
||||
// PodMetrics retrieves all pods metrics
|
||||
func (m *MetricsServer) PodMetrics() (map[string]Metric, error) {
|
||||
mx := map[string]Metric{}
|
||||
|
||||
mm, err := m.getPodMetrics()
|
||||
if err != nil {
|
||||
log.Warn().Msgf("%s", err)
|
||||
return mx, err
|
||||
}
|
||||
|
||||
for _, m := range mm.Items {
|
||||
var cpu, mem int64
|
||||
for _, c := range m.Containers {
|
||||
cpu += c.Usage.Cpu().MilliValue()
|
||||
mem += c.Usage.Memory().Value() / (1024 * 1024)
|
||||
}
|
||||
pa := path.Join(m.Namespace, m.Name)
|
||||
mx[pa] = Metric{CPU: fmt.Sprintf("%dm", cpu), Mem: fmt.Sprintf("%dMi", mem)}
|
||||
}
|
||||
|
||||
return mx, nil
|
||||
}
|
||||
|
||||
// PerNodeMetrics retrieves all nodes metrics
|
||||
func (m *MetricsServer) PerNodeMetrics(nn []v1.Node) (map[string]Metric, error) {
|
||||
mx := map[string]Metric{}
|
||||
|
||||
mm, err := m.getNodeMetrics()
|
||||
if err != nil {
|
||||
log.Warn().Msgf("%s", err)
|
||||
return mx, err
|
||||
}
|
||||
|
||||
for _, n := range nn {
|
||||
acpu := n.Status.Allocatable["cpu"]
|
||||
amem := n.Status.Allocatable["memory"]
|
||||
var cpu, mem int64
|
||||
for _, m := range mm.Items {
|
||||
if m.Name == n.Name {
|
||||
cpu += m.Usage.Cpu().MilliValue()
|
||||
mem += m.Usage.Memory().Value() / (1024 * 1024)
|
||||
}
|
||||
}
|
||||
mx[n.Name] = Metric{
|
||||
CPU: fmt.Sprintf("%dm", cpu),
|
||||
Mem: fmt.Sprintf("%dMi", mem),
|
||||
AvailCPU: fmt.Sprintf("%dm", acpu.MilliValue()),
|
||||
AvailMem: fmt.Sprintf("%dMi", amem.Value()/(1024*1024)),
|
||||
// NodesMetrics retrieves metrics for a given set of nodes.
|
||||
func (m *MetricsServer) NodesMetrics(nodes []v1.Node, metrics []mv1beta1.NodeMetrics, mmx NodesMetrics) {
|
||||
for _, n := range nodes {
|
||||
mmx[n.Name] = NodeMetrics{
|
||||
AvailCPU: n.Status.Allocatable.Cpu().MilliValue(),
|
||||
AvailMEM: asMi(n.Status.Allocatable.Memory().Value()),
|
||||
TotalCPU: n.Status.Capacity.Cpu().MilliValue(),
|
||||
TotalMEM: asMi(n.Status.Capacity.Memory().Value()),
|
||||
}
|
||||
}
|
||||
|
||||
return mx, nil
|
||||
for _, c := range metrics {
|
||||
if mx, ok := mmx[c.Name]; ok {
|
||||
mx.CurrentCPU = c.Usage.Cpu().MilliValue()
|
||||
mx.CurrentMEM = asMi(c.Usage.Memory().Value())
|
||||
mmx[c.Name] = mx
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MetricsServer) getPodMetrics() (*metricsapi.PodMetricsList, error) {
|
||||
if conn.hasMetricsServer() {
|
||||
return m.podMetricsViaService()
|
||||
// ClusterLoad retrieves all cluster nodes metrics.
|
||||
func (m *MetricsServer) ClusterLoad(nodes []v1.Node, metrics []mv1beta1.NodeMetrics) ClusterMetrics {
|
||||
nodeMetrics := make(NodesMetrics, len(nodes))
|
||||
|
||||
for _, n := range nodes {
|
||||
nodeMetrics[n.Name] = NodeMetrics{
|
||||
AvailCPU: n.Status.Allocatable.Cpu().MilliValue(),
|
||||
AvailMEM: asMi(n.Status.Allocatable.Memory().Value()),
|
||||
TotalCPU: n.Status.Capacity.Cpu().MilliValue(),
|
||||
TotalMEM: asMi(n.Status.Capacity.Memory().Value()),
|
||||
}
|
||||
}
|
||||
|
||||
var mx *metricsapi.PodMetricsList
|
||||
conn, err := conn.heapsterDial()
|
||||
if err != nil {
|
||||
log.Warn().Msgf("%s", err)
|
||||
return mx, err
|
||||
for _, mx := range metrics {
|
||||
if m, ok := nodeMetrics[mx.Name]; ok {
|
||||
m.CurrentCPU = mx.Usage.Cpu().MilliValue()
|
||||
m.CurrentMEM = asMi(mx.Usage.Memory().Value())
|
||||
nodeMetrics[mx.Name] = m
|
||||
}
|
||||
}
|
||||
|
||||
return conn.GetPodMetrics("", "", true, labels.Everything())
|
||||
var cpu, tcpu, mem, tmem float64
|
||||
for _, mx := range nodeMetrics {
|
||||
cpu += float64(mx.CurrentCPU)
|
||||
tcpu += float64(mx.TotalCPU)
|
||||
mem += mx.CurrentMEM
|
||||
tmem += mx.TotalMEM
|
||||
}
|
||||
|
||||
return ClusterMetrics{PercCPU: toPerc(cpu, tcpu), PercMEM: toPerc(mem, tmem)}
|
||||
}
|
||||
|
||||
func (m *MetricsServer) getNodeMetrics() (*metricsapi.NodeMetricsList, error) {
|
||||
if conn.hasMetricsServer() {
|
||||
return m.nodeMetricsViaService()
|
||||
}
|
||||
// // HasMetrics check if cluster has a metrics server.
|
||||
// func (m *MetricsServer) HasMetrics() bool {
|
||||
// return m.HasMetrics()
|
||||
// }
|
||||
|
||||
var mx *metricsapi.NodeMetricsList
|
||||
conn, err := conn.heapsterDial()
|
||||
// FetchNodesMetrics return all metrics for pods in a given namespace.
|
||||
func (m *MetricsServer) FetchNodesMetrics() ([]mv1beta1.NodeMetrics, error) {
|
||||
client, err := m.MXDial()
|
||||
if err != nil {
|
||||
log.Warn().Msgf("%s", err)
|
||||
return mx, err
|
||||
}
|
||||
|
||||
return conn.GetNodeMetrics("", labels.Everything().String())
|
||||
}
|
||||
|
||||
func (*MetricsServer) nodeMetricsViaService() (*metricsapi.NodeMetricsList, error) {
|
||||
var mx *metricsapi.NodeMetricsList
|
||||
|
||||
clt, err := conn.mxsDial()
|
||||
if err != nil {
|
||||
log.Warn().Msgf("%s", err)
|
||||
return mx, err
|
||||
}
|
||||
|
||||
selector := labels.Everything()
|
||||
var versionedMetrics *metricsV1beta1api.NodeMetricsList
|
||||
mc := clt.Metrics()
|
||||
nm := mc.NodeMetricses()
|
||||
versionedMetrics, err = nm.List(metav1.ListOptions{LabelSelector: selector.String()})
|
||||
if err != nil {
|
||||
log.Warn().Msgf("%s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
metrics := &metricsapi.NodeMetricsList{}
|
||||
err = metricsV1beta1api.Convert_v1beta1_NodeMetricsList_To_metrics_NodeMetricsList(versionedMetrics, metrics, nil)
|
||||
list, err := client.Metrics().NodeMetricses().List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
log.Warn().Msgf("%s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return metrics, nil
|
||||
return list.Items, nil
|
||||
}
|
||||
|
||||
func (*MetricsServer) podMetricsViaService() (*metricsapi.PodMetricsList, error) {
|
||||
var mx *metricsapi.PodMetricsList
|
||||
|
||||
clt, err := conn.mxsDial()
|
||||
// FetchPodsMetrics return all metrics for pods in a given namespace.
|
||||
func (m *MetricsServer) FetchPodsMetrics(ns string) ([]mv1beta1.PodMetrics, error) {
|
||||
client, err := m.MXDial()
|
||||
if err != nil {
|
||||
log.Warn().Msgf("%s", err)
|
||||
return mx, err
|
||||
}
|
||||
|
||||
selector := labels.Everything()
|
||||
var versionedMetrics *metricsV1beta1api.PodMetricsList
|
||||
mc := clt.Metrics()
|
||||
nm := mc.PodMetricses("")
|
||||
versionedMetrics, err = nm.List(metav1.ListOptions{LabelSelector: selector.String()})
|
||||
if err != nil {
|
||||
log.Warn().Msgf("%s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
metrics := &metricsapi.PodMetricsList{}
|
||||
err = metricsV1beta1api.Convert_v1beta1_PodMetricsList_To_metrics_PodMetricsList(versionedMetrics, metrics, nil)
|
||||
list, err := client.Metrics().PodMetricses(ns).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
log.Warn().Msgf("%s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return metrics, nil
|
||||
return list.Items, nil
|
||||
}
|
||||
|
||||
// PodsMetrics retrieves metrics for all pods in a given namespace.
|
||||
func (m *MetricsServer) PodsMetrics(pods []mv1beta1.PodMetrics, mmx PodsMetrics) {
|
||||
// Compute all pod's containers metrics.
|
||||
for _, p := range pods {
|
||||
var mx PodMetrics
|
||||
for _, c := range p.Containers {
|
||||
mx.CurrentCPU += c.Usage.Cpu().MilliValue()
|
||||
mx.CurrentMEM += asMi(c.Usage.Memory().Value())
|
||||
}
|
||||
mmx[p.Namespace+"/"+p.Name] = mx
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,196 @@
|
|||
package k8s
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
v1beta1 "k8s.io/metrics/pkg/apis/metrics/v1beta1"
|
||||
)
|
||||
|
||||
func TestPodsMetrics(t *testing.T) {
|
||||
m := NewMetricsServer(nil)
|
||||
|
||||
metrics := v1beta1.PodMetricsList{
|
||||
Items: []v1beta1.PodMetrics{
|
||||
makeMxPod("p1", "1", "4Gi"),
|
||||
makeMxPod("p2", "50m", "1Mi"),
|
||||
},
|
||||
}
|
||||
|
||||
mmx := make(PodsMetrics)
|
||||
m.PodsMetrics(metrics.Items, mmx)
|
||||
assert.Equal(t, 2, len(mmx))
|
||||
|
||||
mx, ok := mmx["default/p1"]
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, int64(3000), mx.CurrentCPU)
|
||||
assert.Equal(t, float64(12288), mx.CurrentMEM)
|
||||
}
|
||||
|
||||
func BenchmarkPodsMetrics(b *testing.B) {
|
||||
m := NewMetricsServer(nil)
|
||||
|
||||
metrics := v1beta1.PodMetricsList{
|
||||
Items: []v1beta1.PodMetrics{
|
||||
makeMxPod("p1", "1", "4Gi"),
|
||||
makeMxPod("p2", "50m", "1Mi"),
|
||||
makeMxPod("p3", "50m", "1Mi"),
|
||||
},
|
||||
}
|
||||
mmx := make(PodsMetrics, 3)
|
||||
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for n := 0; n < b.N; n++ {
|
||||
m.PodsMetrics(metrics.Items, mmx)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNodesMetrics(t *testing.T) {
|
||||
m := NewMetricsServer(nil)
|
||||
|
||||
nodes := v1.NodeList{
|
||||
Items: []v1.Node{
|
||||
makeNode("n1", "32", "128Gi", "50m", "2Mi"),
|
||||
makeNode("n2", "8", "4Gi", "50m", "2Mi"),
|
||||
},
|
||||
}
|
||||
|
||||
metrics := v1beta1.NodeMetricsList{
|
||||
Items: []v1beta1.NodeMetrics{
|
||||
makeMxNode("n1", "10", "8Gi"),
|
||||
makeMxNode("n2", "50m", "1Mi"),
|
||||
},
|
||||
}
|
||||
|
||||
mmx := make(NodesMetrics)
|
||||
m.NodesMetrics(nodes.Items, metrics.Items, mmx)
|
||||
assert.Equal(t, 2, len(mmx))
|
||||
mx, ok := mmx["n1"]
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, int64(32000), mx.TotalCPU)
|
||||
assert.Equal(t, float64(131072), mx.TotalMEM)
|
||||
assert.Equal(t, int64(50), mx.AvailCPU)
|
||||
assert.Equal(t, float64(2), mx.AvailMEM)
|
||||
assert.Equal(t, int64(10000), mx.CurrentCPU)
|
||||
assert.Equal(t, float64(8192), mx.CurrentMEM)
|
||||
}
|
||||
|
||||
func BenchmarkNodesMetrics(b *testing.B) {
|
||||
nodes := v1.NodeList{
|
||||
Items: []v1.Node{
|
||||
makeNode("n1", "100m", "4Mi", "50m", "2Mi"),
|
||||
makeNode("n2", "100m", "4Mi", "50m", "2Mi"),
|
||||
},
|
||||
}
|
||||
|
||||
metrics := v1beta1.NodeMetricsList{
|
||||
Items: []v1beta1.NodeMetrics{
|
||||
makeMxNode("n1", "50m", "1Mi"),
|
||||
makeMxNode("n2", "50m", "1Mi"),
|
||||
},
|
||||
}
|
||||
|
||||
m := NewMetricsServer(nil)
|
||||
mmx := make(NodesMetrics)
|
||||
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for n := 0; n < b.N; n++ {
|
||||
m.NodesMetrics(nodes.Items, metrics.Items, mmx)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClusterLoad(t *testing.T) {
|
||||
m := NewMetricsServer(nil)
|
||||
|
||||
nodes := v1.NodeList{
|
||||
Items: []v1.Node{
|
||||
makeNode("n1", "100m", "4Mi", "50m", "2Mi"),
|
||||
makeNode("n2", "100m", "4Mi", "50m", "2Mi"),
|
||||
},
|
||||
}
|
||||
|
||||
metrics := v1beta1.NodeMetricsList{
|
||||
Items: []v1beta1.NodeMetrics{
|
||||
makeMxNode("n1", "50m", "1Mi"),
|
||||
makeMxNode("n2", "50m", "1Mi"),
|
||||
},
|
||||
}
|
||||
|
||||
mx := m.ClusterLoad(nodes.Items, metrics.Items)
|
||||
assert.Equal(t, 50.0, mx.PercCPU)
|
||||
assert.Equal(t, 25.0, mx.PercMEM)
|
||||
}
|
||||
|
||||
func BenchmarkClusterLoad(b *testing.B) {
|
||||
nodes := v1.NodeList{
|
||||
Items: []v1.Node{
|
||||
makeNode("n1", "100m", "4Mi", "50m", "2Mi"),
|
||||
makeNode("n2", "100m", "4Mi", "50m", "2Mi"),
|
||||
},
|
||||
}
|
||||
|
||||
metrics := v1beta1.NodeMetricsList{
|
||||
Items: []v1beta1.NodeMetrics{
|
||||
makeMxNode("n1", "50m", "1Mi"),
|
||||
makeMxNode("n2", "50m", "1Mi"),
|
||||
},
|
||||
}
|
||||
|
||||
m := NewMetricsServer(nil)
|
||||
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for n := 0; n < b.N; n++ {
|
||||
m.ClusterLoad(nodes.Items, metrics.Items)
|
||||
}
|
||||
}
|
||||
|
||||
func makeMxPod(name, cpu, mem string) v1beta1.PodMetrics {
|
||||
return v1beta1.PodMetrics{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: "default",
|
||||
},
|
||||
Containers: []v1beta1.ContainerMetrics{
|
||||
{Usage: makeRes(cpu, mem)},
|
||||
{Usage: makeRes(cpu, mem)},
|
||||
{Usage: makeRes(cpu, mem)},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func makeNode(name, tcpu, tmem, acpu, amem string) v1.Node {
|
||||
return v1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
},
|
||||
Status: v1.NodeStatus{
|
||||
Capacity: makeRes(tcpu, tmem),
|
||||
Allocatable: makeRes(acpu, amem),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func makeMxNode(name, cpu, mem string) v1beta1.NodeMetrics {
|
||||
return v1beta1.NodeMetrics{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
},
|
||||
Usage: makeRes(cpu, mem),
|
||||
}
|
||||
}
|
||||
|
||||
func makeRes(c, m string) v1.ResourceList {
|
||||
cpu, _ := resource.ParseQuantity(c)
|
||||
mem, _ := resource.ParseQuantity(m)
|
||||
|
||||
return v1.ResourceList{
|
||||
v1.ResourceCPU: cpu,
|
||||
v1.ResourceMemory: mem,
|
||||
}
|
||||
}
|
||||
|
|
@ -5,28 +5,26 @@ import (
|
|||
)
|
||||
|
||||
// Node represents a Kubernetes node.
|
||||
type Node struct{}
|
||||
type Node struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewNode returns a new Node.
|
||||
func NewNode() Res {
|
||||
return &Node{}
|
||||
func NewNode(c Connection) Cruder {
|
||||
return &Node{c}
|
||||
}
|
||||
|
||||
// Get a node.
|
||||
func (*Node) Get(_, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().CoreV1().Nodes().Get(n, opts)
|
||||
func (n *Node) Get(_, name string) (interface{}, error) {
|
||||
return n.DialOrDie().CoreV1().Nodes().Get(name, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all nodes on the cluster.
|
||||
func (*Node) List(_ string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().CoreV1().Nodes().List(opts)
|
||||
func (n *Node) List(_ string) (Collection, error) {
|
||||
rr, err := n.DialOrDie().CoreV1().Nodes().List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -36,7 +34,6 @@ func (*Node) List(_ string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete a node.
|
||||
func (*Node) Delete(_, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().CoreV1().Nodes().Delete(n, &opts)
|
||||
func (n *Node) Delete(_, name string) error {
|
||||
return n.DialOrDie().CoreV1().Nodes().Delete(name, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,29 +5,26 @@ import (
|
|||
)
|
||||
|
||||
// Namespace represents a Kubernetes namespace.
|
||||
type Namespace struct{}
|
||||
type Namespace struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewNamespace returns a new Namespace.
|
||||
func NewNamespace() Res {
|
||||
return &Namespace{}
|
||||
func NewNamespace(c Connection) Cruder {
|
||||
return &Namespace{c}
|
||||
}
|
||||
|
||||
// Get a active namespace.
|
||||
func (*Namespace) Get(_, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
|
||||
return conn.dialOrDie().CoreV1().Namespaces().Get(n, opts)
|
||||
func (n *Namespace) Get(_, name string) (interface{}, error) {
|
||||
return n.DialOrDie().CoreV1().Namespaces().Get(name, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all active namespaces on the cluster.
|
||||
func (*Namespace) List(_ string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().CoreV1().Namespaces().List(opts)
|
||||
func (n *Namespace) List(_ string) (Collection, error) {
|
||||
rr, err := n.DialOrDie().CoreV1().Namespaces().List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -37,8 +34,6 @@ func (*Namespace) List(_ string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete a namespace.
|
||||
func (*Namespace) Delete(_, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
|
||||
return conn.dialOrDie().CoreV1().Namespaces().Delete(n, &opts)
|
||||
func (n *Namespace) Delete(_, name string) error {
|
||||
return n.DialOrDie().CoreV1().Namespaces().Delete(name, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,28 +5,26 @@ import (
|
|||
)
|
||||
|
||||
// PodDisruptionBudget represents a PodDisruptionBudget Kubernetes resource.
|
||||
type PodDisruptionBudget struct{}
|
||||
type PodDisruptionBudget struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewPodDisruptionBudget returns a new PodDisruptionBudget.
|
||||
func NewPodDisruptionBudget() Res {
|
||||
return &PodDisruptionBudget{}
|
||||
func NewPodDisruptionBudget(c Connection) Cruder {
|
||||
return &PodDisruptionBudget{c}
|
||||
}
|
||||
|
||||
// Get a pdb.
|
||||
func (*PodDisruptionBudget) Get(ns, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().PolicyV1beta1().PodDisruptionBudgets(ns).Get(n, opts)
|
||||
func (p *PodDisruptionBudget) Get(ns, n string) (interface{}, error) {
|
||||
return p.DialOrDie().PolicyV1beta1().PodDisruptionBudgets(ns).Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all pdbs in a given namespace.
|
||||
func (*PodDisruptionBudget) List(ns string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().PolicyV1beta1().PodDisruptionBudgets(ns).List(opts)
|
||||
func (p *PodDisruptionBudget) List(ns string) (Collection, error) {
|
||||
rr, err := p.DialOrDie().PolicyV1beta1().PodDisruptionBudgets(ns).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -36,7 +34,6 @@ func (*PodDisruptionBudget) List(ns string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete a pdb.
|
||||
func (*PodDisruptionBudget) Delete(ns, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().PolicyV1beta1().PodDisruptionBudgets(ns).Delete(n, &opts)
|
||||
func (p *PodDisruptionBudget) Delete(ns, n string) error {
|
||||
return p.DialOrDie().PolicyV1beta1().PodDisruptionBudgets(ns).Delete(n, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,38 +8,27 @@ import (
|
|||
|
||||
const defaultKillGrace int64 = 5
|
||||
|
||||
type (
|
||||
// Loggable represents a K8s resource that has containers and can be logged.
|
||||
Loggable interface {
|
||||
Res
|
||||
Containers(ns, n string, includeInit bool) ([]string, error)
|
||||
Logs(ns, n, co string, lines int64, previous bool) *restclient.Request
|
||||
}
|
||||
|
||||
// Pod represents a Kubernetes resource.
|
||||
Pod struct{}
|
||||
)
|
||||
// Pod represents a Kubernetes resource.
|
||||
type Pod struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewPod returns a new Pod.
|
||||
func NewPod() Res {
|
||||
return &Pod{}
|
||||
func NewPod(c Connection) Cruder {
|
||||
return &Pod{c}
|
||||
}
|
||||
|
||||
// Get a pod.
|
||||
func (*Pod) Get(ns, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().CoreV1().Pods(ns).Get(n, opts)
|
||||
func (p *Pod) Get(ns, name string) (interface{}, error) {
|
||||
return p.DialOrDie().CoreV1().Pods(ns).Get(name, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all pods in a given namespace.
|
||||
func (*Pod) List(ns string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().CoreV1().Pods(ns).List(opts)
|
||||
func (p *Pod) List(ns string) (Collection, error) {
|
||||
rr, err := p.DialOrDie().CoreV1().Pods(ns).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -49,51 +38,40 @@ func (*Pod) List(ns string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete a pod.
|
||||
func (*Pod) Delete(ns, n string) error {
|
||||
var grace = defaultKillGrace
|
||||
opts := metav1.DeleteOptions{
|
||||
func (p *Pod) Delete(ns, n string) error {
|
||||
// Make pods die faster?
|
||||
grace := defaultKillGrace
|
||||
return p.DialOrDie().CoreV1().Pods(ns).Delete(n, &metav1.DeleteOptions{
|
||||
GracePeriodSeconds: &grace,
|
||||
}
|
||||
return conn.dialOrDie().CoreV1().Pods(ns).Delete(n, &opts)
|
||||
})
|
||||
}
|
||||
|
||||
// Containers returns all container names on pod
|
||||
func (*Pod) Containers(ns, n string, includeInit bool) ([]string, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
cc := []string{}
|
||||
po, err := conn.dialOrDie().CoreV1().Pods(ns).Get(n, opts)
|
||||
func (p *Pod) Containers(ns, n string, includeInit bool) ([]string, error) {
|
||||
po, err := p.DialOrDie().CoreV1().Pods(ns).Get(n, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return cc, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, c := range po.Spec.Containers {
|
||||
cc = append(cc, c.Name)
|
||||
}
|
||||
cc := []string{}
|
||||
if includeInit {
|
||||
for _, c := range po.Spec.InitContainers {
|
||||
cc = append(cc, c.Name)
|
||||
}
|
||||
}
|
||||
for _, c := range po.Spec.Containers {
|
||||
cc = append(cc, c.Name)
|
||||
}
|
||||
|
||||
return cc, nil
|
||||
}
|
||||
|
||||
// Logs fetch container logs for a given pod and container.
|
||||
func (*Pod) Logs(ns, n, co string, lines int64, prev bool) *restclient.Request {
|
||||
opts := &v1.PodLogOptions{
|
||||
func (p *Pod) Logs(ns, n, co string, lines int64, prev bool) *restclient.Request {
|
||||
return p.DialOrDie().CoreV1().Pods(ns).GetLogs(n, &v1.PodLogOptions{
|
||||
Container: co,
|
||||
Follow: true,
|
||||
TailLines: &lines,
|
||||
Previous: prev,
|
||||
}
|
||||
|
||||
return conn.dialOrDie().CoreV1().Pods(ns).GetLogs(n, opts)
|
||||
}
|
||||
|
||||
// Events retrieved pod's events.
|
||||
func (*Pod) Events(ns, n string) (*v1.EventList, error) {
|
||||
e := conn.dialOrDie().Core().Events(ns)
|
||||
sel := e.GetFieldSelector(&n, &ns, nil, nil)
|
||||
opts := metav1.ListOptions{FieldSelector: sel.String()}
|
||||
ee, err := e.List(opts)
|
||||
return ee, err
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,26 +5,25 @@ import (
|
|||
)
|
||||
|
||||
// PV represents a Kubernetes PersistentVolume.
|
||||
type PV struct{}
|
||||
type PV struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewPV returns a new PV.
|
||||
func NewPV() Res {
|
||||
return &PV{}
|
||||
func NewPV(c Connection) Cruder {
|
||||
return &PV{c}
|
||||
}
|
||||
|
||||
// Get a PV.
|
||||
func (*PV) Get(_, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().CoreV1().PersistentVolumes().Get(n, opts)
|
||||
func (p *PV) Get(_, n string) (interface{}, error) {
|
||||
return p.DialOrDie().CoreV1().PersistentVolumes().Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all PVs in a given namespace.
|
||||
func (*PV) List(_ string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().CoreV1().PersistentVolumes().List(opts)
|
||||
func (p *PV) List(_ string) (Collection, error) {
|
||||
rr, err := p.DialOrDie().CoreV1().PersistentVolumes().List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
|
|
@ -36,7 +35,6 @@ func (*PV) List(_ string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete a PV.
|
||||
func (*PV) Delete(_, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().CoreV1().PersistentVolumes().Delete(n, &opts)
|
||||
func (p *PV) Delete(_, n string) error {
|
||||
return p.DialOrDie().CoreV1().PersistentVolumes().Delete(n, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,28 +5,26 @@ import (
|
|||
)
|
||||
|
||||
// PVC represents a Kubernetes service.
|
||||
type PVC struct{}
|
||||
type PVC struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewPVC returns a new PVC.
|
||||
func NewPVC() Res {
|
||||
return &PVC{}
|
||||
func NewPVC(c Connection) Cruder {
|
||||
return &PVC{c}
|
||||
}
|
||||
|
||||
// Get a PVC.
|
||||
func (*PVC) Get(ns, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().CoreV1().PersistentVolumeClaims(ns).Get(n, opts)
|
||||
func (p *PVC) Get(ns, n string) (interface{}, error) {
|
||||
return p.DialOrDie().CoreV1().PersistentVolumeClaims(ns).Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all PVCs in a given namespace.
|
||||
func (*PVC) List(ns string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().CoreV1().PersistentVolumeClaims(ns).List(opts)
|
||||
func (p *PVC) List(ns string) (Collection, error) {
|
||||
rr, err := p.DialOrDie().CoreV1().PersistentVolumeClaims(ns).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -36,7 +34,6 @@ func (*PVC) List(ns string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete a PVC.
|
||||
func (*PVC) Delete(ns, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().CoreV1().PersistentVolumeClaims(ns).Delete(n, &opts)
|
||||
func (p *PVC) Delete(ns, n string) error {
|
||||
return p.DialOrDie().CoreV1().PersistentVolumeClaims(ns).Delete(n, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,28 +5,26 @@ import (
|
|||
)
|
||||
|
||||
// ReplicationController represents a Kubernetes service.
|
||||
type ReplicationController struct{}
|
||||
type ReplicationController struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewReplicationController returns a new ReplicationController.
|
||||
func NewReplicationController() Res {
|
||||
return &ReplicationController{}
|
||||
func NewReplicationController(c Connection) Cruder {
|
||||
return &ReplicationController{c}
|
||||
}
|
||||
|
||||
// Get a RC.
|
||||
func (*ReplicationController) Get(ns, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().Core().ReplicationControllers(ns).Get(n, opts)
|
||||
func (r *ReplicationController) Get(ns, n string) (interface{}, error) {
|
||||
return r.DialOrDie().Core().ReplicationControllers(ns).Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all RCs in a given namespace.
|
||||
func (*ReplicationController) List(ns string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().Core().ReplicationControllers(ns).List(opts)
|
||||
func (r *ReplicationController) List(ns string) (Collection, error) {
|
||||
rr, err := r.DialOrDie().Core().ReplicationControllers(ns).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -36,7 +34,6 @@ func (*ReplicationController) List(ns string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete a RC.
|
||||
func (*ReplicationController) Delete(ns, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().Core().ReplicationControllers(ns).Delete(n, &opts)
|
||||
func (r *ReplicationController) Delete(ns, n string) error {
|
||||
return r.DialOrDie().Core().ReplicationControllers(ns).Delete(n, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package k8s
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
|
@ -15,12 +14,14 @@ import (
|
|||
|
||||
// Resource represents a Kubernetes Resource
|
||||
type Resource struct {
|
||||
Connection
|
||||
|
||||
group, version, name string
|
||||
}
|
||||
|
||||
// NewResource returns a new Resource.
|
||||
func NewResource(group, version, name string) Res {
|
||||
return &Resource{group: group, version: version, name: name}
|
||||
func NewResource(c Connection, group, version, name string) Cruder {
|
||||
return &Resource{Connection: c, group: group, version: version, name: name}
|
||||
}
|
||||
|
||||
// GetInfo returns info about apigroup.
|
||||
|
|
@ -34,48 +35,82 @@ func (r *Resource) base() dynamic.NamespaceableResourceInterface {
|
|||
Version: r.version,
|
||||
Resource: r.name,
|
||||
}
|
||||
return conn.dynDialOrDie().Resource(g)
|
||||
return r.DynDialOrDie().Resource(g)
|
||||
}
|
||||
|
||||
// Get a Resource.
|
||||
func (r *Resource) Get(ns, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return r.base().Namespace(ns).Get(n, opts)
|
||||
return r.base().Namespace(ns).Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all Resources in a given namespace.
|
||||
func (r *Resource) List(ns string) (Collection, error) {
|
||||
obj, err := r.listAll(ns, r.name)
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return Collection{obj.(*metav1beta1.Table)}, nil
|
||||
}
|
||||
|
||||
// Delete a Resource.
|
||||
func (r *Resource) Delete(ns, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return r.base().Namespace(ns).Delete(n, &opts)
|
||||
return r.base().Namespace(ns).Delete(n, nil)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Helpers...
|
||||
|
||||
func (r *Resource) getClient() *rest.RESTClient {
|
||||
gv := schema.GroupVersion{Group: r.group, Version: r.version}
|
||||
codecs, _ := r.codecs()
|
||||
crConfig := *conn.restConfigOrDie()
|
||||
crConfig.GroupVersion = &gv
|
||||
const gvFmt = "application/json;as=Table;v=%s;g=%s, application/json"
|
||||
|
||||
func (r *Resource) listAll(ns, n string) (runtime.Object, error) {
|
||||
a := fmt.Sprintf(gvFmt, metav1beta1.SchemeGroupVersion.Version, metav1beta1.GroupName)
|
||||
_, codec := r.codecs()
|
||||
|
||||
c, err := r.getClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.Get().
|
||||
SetHeader("Accept", a).
|
||||
Namespace(ns).
|
||||
Resource(n).
|
||||
VersionedParams(&metav1beta1.TableOptions{}, codec).
|
||||
Do().Get()
|
||||
}
|
||||
|
||||
func (r *Resource) getOne(ns, n string) (runtime.Object, error) {
|
||||
a := fmt.Sprintf(gvFmt, metav1beta1.SchemeGroupVersion.Version, metav1beta1.GroupName)
|
||||
_, codec := r.codecs()
|
||||
|
||||
c, err := r.getClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.Get().
|
||||
SetHeader("Accept", a).
|
||||
Namespace(ns).
|
||||
Resource(n).
|
||||
VersionedParams(&metav1beta1.TableOptions{}, codec).
|
||||
Do().Get()
|
||||
}
|
||||
|
||||
func (r *Resource) getClient() (*rest.RESTClient, error) {
|
||||
crConfig := r.RestConfigOrDie()
|
||||
crConfig.GroupVersion = &schema.GroupVersion{Group: r.group, Version: r.version}
|
||||
crConfig.APIPath = "/apis"
|
||||
if len(r.group) == 0 {
|
||||
crConfig.APIPath = "/api"
|
||||
}
|
||||
codecs, _ := r.codecs()
|
||||
crConfig.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: codecs}
|
||||
crRestClient, err := rest.RESTClientFor(&crConfig)
|
||||
|
||||
crRestClient, err := rest.RESTClientFor(crConfig)
|
||||
if err != nil {
|
||||
log.Fatal().Err(err)
|
||||
return nil, err
|
||||
}
|
||||
return crRestClient
|
||||
return crRestClient, nil
|
||||
}
|
||||
|
||||
func (r *Resource) codecs() (serializer.CodecFactory, runtime.ParameterCodec) {
|
||||
|
|
@ -84,36 +119,6 @@ func (r *Resource) codecs() (serializer.CodecFactory, runtime.ParameterCodec) {
|
|||
metav1.AddToGroupVersion(scheme, gv)
|
||||
scheme.AddKnownTypes(gv, &metav1beta1.Table{}, &metav1beta1.TableOptions{})
|
||||
scheme.AddKnownTypes(metav1beta1.SchemeGroupVersion, &metav1beta1.Table{}, &metav1beta1.TableOptions{})
|
||||
codecs := serializer.NewCodecFactory(scheme)
|
||||
return codecs, runtime.NewParameterCodec(scheme)
|
||||
}
|
||||
|
||||
func (r *Resource) listAll(ns, n string) (runtime.Object, error) {
|
||||
group := metav1beta1.GroupName
|
||||
version := metav1beta1.SchemeGroupVersion.Version
|
||||
a := fmt.Sprintf("application/json;as=Table;v=%s;g=%s, application/json", version, group)
|
||||
|
||||
_, codec := r.codecs()
|
||||
return r.getClient().Get().
|
||||
SetHeader("Accept", a).
|
||||
Namespace(ns).
|
||||
Resource(n).
|
||||
VersionedParams(&metav1beta1.TableOptions{}, codec).
|
||||
Do().
|
||||
Get()
|
||||
}
|
||||
|
||||
func (r *Resource) getOne(ns, n string) (runtime.Object, error) {
|
||||
group := metav1beta1.GroupName
|
||||
version := metav1beta1.SchemeGroupVersion.Version
|
||||
a := fmt.Sprintf("application/json;as=Table;v=%s;g=%s, application/json", version, group)
|
||||
|
||||
_, codec := r.codecs()
|
||||
return r.getClient().Get().
|
||||
SetHeader("Accept", a).
|
||||
Namespace(ns).
|
||||
Resource(n).
|
||||
VersionedParams(&metav1beta1.TableOptions{}, codec).
|
||||
Do().
|
||||
Get()
|
||||
|
||||
return serializer.NewCodecFactory(scheme), runtime.NewParameterCodec(scheme)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,28 +6,26 @@ import (
|
|||
)
|
||||
|
||||
// Role represents a Kubernetes Role.
|
||||
type Role struct{}
|
||||
type Role struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewRole returns a new Role.
|
||||
func NewRole() Res {
|
||||
return &Role{}
|
||||
func NewRole(c Connection) Cruder {
|
||||
return &Role{c}
|
||||
}
|
||||
|
||||
// Get a Role.
|
||||
func (*Role) Get(ns, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().RbacV1().Roles(ns).Get(n, opts)
|
||||
func (r *Role) Get(ns, n string) (interface{}, error) {
|
||||
return r.DialOrDie().RbacV1().Roles(ns).Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all Roles in a given namespace.
|
||||
func (*Role) List(ns string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().RbacV1().Roles(ns).List(opts)
|
||||
func (r *Role) List(ns string) (Collection, error) {
|
||||
rr, err := r.DialOrDie().RbacV1().Roles(ns).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -37,7 +35,6 @@ func (*Role) List(ns string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete a Role.
|
||||
func (*Role) Delete(ns, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().RbacV1().Roles(ns).Delete(n, &opts)
|
||||
func (r *Role) Delete(ns, n string) error {
|
||||
return r.DialOrDie().RbacV1().Roles(ns).Delete(n, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,28 +3,26 @@ package k8s
|
|||
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
// RoleBinding represents a Kubernetes RoleBinding.
|
||||
type RoleBinding struct{}
|
||||
type RoleBinding struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewRoleBinding returns a new RoleBinding.
|
||||
func NewRoleBinding() Res {
|
||||
return &RoleBinding{}
|
||||
func NewRoleBinding(c Connection) Cruder {
|
||||
return &RoleBinding{c}
|
||||
}
|
||||
|
||||
// Get a RoleBinding.
|
||||
func (*RoleBinding) Get(ns, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().RbacV1().RoleBindings(ns).Get(n, opts)
|
||||
func (r *RoleBinding) Get(ns, n string) (interface{}, error) {
|
||||
return r.DialOrDie().RbacV1().RoleBindings(ns).Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all RoleBindings in a given namespace.
|
||||
func (*RoleBinding) List(ns string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().RbacV1().RoleBindings(ns).List(opts)
|
||||
func (r *RoleBinding) List(ns string) (Collection, error) {
|
||||
rr, err := r.DialOrDie().RbacV1().RoleBindings(ns).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -34,7 +32,6 @@ func (*RoleBinding) List(ns string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete a RoleBinding.
|
||||
func (*RoleBinding) Delete(ns, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().RbacV1().RoleBindings(ns).Delete(n, &opts)
|
||||
func (r *RoleBinding) Delete(ns, n string) error {
|
||||
return r.DialOrDie().RbacV1().RoleBindings(ns).Delete(n, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,28 +5,26 @@ import (
|
|||
)
|
||||
|
||||
// ReplicaSet represents a Kubernetes ReplicaSet.
|
||||
type ReplicaSet struct{}
|
||||
type ReplicaSet struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewReplicaSet returns a new ReplicaSet.
|
||||
func NewReplicaSet() Res {
|
||||
return &ReplicaSet{}
|
||||
func NewReplicaSet(c Connection) Cruder {
|
||||
return &ReplicaSet{c}
|
||||
}
|
||||
|
||||
// Get a ReplicaSet.
|
||||
func (*ReplicaSet) Get(ns, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().Apps().ReplicaSets(ns).Get(n, opts)
|
||||
func (r *ReplicaSet) Get(ns, n string) (interface{}, error) {
|
||||
return r.DialOrDie().Apps().ReplicaSets(ns).Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all ReplicaSets in a given namespace.
|
||||
func (*ReplicaSet) List(ns string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().Apps().ReplicaSets(ns).List(opts)
|
||||
func (r *ReplicaSet) List(ns string) (Collection, error) {
|
||||
rr, err := r.DialOrDie().Apps().ReplicaSets(ns).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -36,7 +34,6 @@ func (*ReplicaSet) List(ns string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete a ReplicaSet.
|
||||
func (*ReplicaSet) Delete(ns, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().Apps().ReplicaSets(ns).Delete(n, &opts)
|
||||
func (r *ReplicaSet) Delete(ns, n string) error {
|
||||
return r.DialOrDie().Apps().ReplicaSets(ns).Delete(n, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,32 +5,26 @@ import (
|
|||
)
|
||||
|
||||
// ServiceAccount manages a Kubernetes ServiceAccount.
|
||||
type ServiceAccount struct{}
|
||||
type ServiceAccount struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewServiceAccount instantiates a new ServiceAccount.
|
||||
func NewServiceAccount() Res {
|
||||
return &ServiceAccount{}
|
||||
func NewServiceAccount(c Connection) Cruder {
|
||||
return &ServiceAccount{c}
|
||||
}
|
||||
|
||||
// Get a ServiceAccount.
|
||||
func (*ServiceAccount) Get(ns, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
o, err := conn.dialOrDie().CoreV1().ServiceAccounts(ns).Get(n, opts)
|
||||
if err != nil {
|
||||
return o, err
|
||||
}
|
||||
return o, nil
|
||||
func (s *ServiceAccount) Get(ns, n string) (interface{}, error) {
|
||||
return s.DialOrDie().CoreV1().ServiceAccounts(ns).Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all ServiceAccounts in a given namespace.
|
||||
func (*ServiceAccount) List(ns string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().CoreV1().ServiceAccounts(ns).List(opts)
|
||||
func (s *ServiceAccount) List(ns string) (Collection, error) {
|
||||
rr, err := s.DialOrDie().CoreV1().ServiceAccounts(ns).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -40,7 +34,6 @@ func (*ServiceAccount) List(ns string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete a ServiceAccount.
|
||||
func (*ServiceAccount) Delete(ns, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().CoreV1().ServiceAccounts(ns).Delete(n, &opts)
|
||||
func (s *ServiceAccount) Delete(ns, n string) error {
|
||||
return s.DialOrDie().CoreV1().ServiceAccounts(ns).Delete(n, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,28 +5,26 @@ import (
|
|||
)
|
||||
|
||||
// Secret represents a Kubernetes Secret.
|
||||
type Secret struct{}
|
||||
type Secret struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewSecret returns a new Secret.
|
||||
func NewSecret() Res {
|
||||
return &Secret{}
|
||||
func NewSecret(c Connection) Cruder {
|
||||
return &Secret{c}
|
||||
}
|
||||
|
||||
// Get a Secret.
|
||||
func (c *Secret) Get(ns, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().CoreV1().Secrets(ns).Get(n, opts)
|
||||
func (s *Secret) Get(ns, n string) (interface{}, error) {
|
||||
return s.DialOrDie().CoreV1().Secrets(ns).Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all Secrets in a given namespace.
|
||||
func (c *Secret) List(ns string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().CoreV1().Secrets(ns).List(opts)
|
||||
func (s *Secret) List(ns string) (Collection, error) {
|
||||
rr, err := s.DialOrDie().CoreV1().Secrets(ns).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -36,7 +34,6 @@ func (c *Secret) List(ns string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete a Secret.
|
||||
func (c *Secret) Delete(ns, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().CoreV1().Secrets(ns).Delete(n, &opts)
|
||||
func (s *Secret) Delete(ns, n string) error {
|
||||
return s.DialOrDie().CoreV1().Secrets(ns).Delete(n, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,41 +5,35 @@ import (
|
|||
)
|
||||
|
||||
// StatefulSet manages a Kubernetes StatefulSet.
|
||||
type StatefulSet struct{}
|
||||
type StatefulSet struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewStatefulSet instantiates a new StatefulSet.
|
||||
func NewStatefulSet() Res {
|
||||
return &StatefulSet{}
|
||||
func NewStatefulSet(c Connection) Cruder {
|
||||
return &StatefulSet{c}
|
||||
}
|
||||
|
||||
// Get a StatefulSet.
|
||||
func (*StatefulSet) Get(ns, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
o, err := conn.dialOrDie().AppsV1().StatefulSets(ns).Get(n, opts)
|
||||
if err != nil {
|
||||
return o, err
|
||||
}
|
||||
return o, nil
|
||||
func (s *StatefulSet) Get(ns, n string) (interface{}, error) {
|
||||
return s.DialOrDie().AppsV1().StatefulSets(ns).Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all StatefulSets in a given namespace.
|
||||
func (*StatefulSet) List(ns string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().AppsV1().StatefulSets(ns).List(opts)
|
||||
func (s *StatefulSet) List(ns string) (Collection, error) {
|
||||
rr, err := s.DialOrDie().AppsV1().StatefulSets(ns).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
}
|
||||
|
||||
return cc, nil
|
||||
}
|
||||
|
||||
// Delete a StatefulSet.
|
||||
func (*StatefulSet) Delete(ns, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().AppsV1().StatefulSets(ns).Delete(n, &opts)
|
||||
func (s *StatefulSet) Delete(ns, n string) error {
|
||||
return s.DialOrDie().AppsV1().StatefulSets(ns).Delete(n, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,28 +5,26 @@ import (
|
|||
)
|
||||
|
||||
// Service represents a Kubernetes Service.
|
||||
type Service struct{}
|
||||
type Service struct {
|
||||
Connection
|
||||
}
|
||||
|
||||
// NewService returns a new Service.
|
||||
func NewService() Res {
|
||||
return &Service{}
|
||||
func NewService(c Connection) Cruder {
|
||||
return &Service{c}
|
||||
}
|
||||
|
||||
// Get a service.
|
||||
func (*Service) Get(ns, n string) (interface{}, error) {
|
||||
opts := metav1.GetOptions{}
|
||||
return conn.dialOrDie().CoreV1().Services(ns).Get(n, opts)
|
||||
func (s *Service) Get(ns, n string) (interface{}, error) {
|
||||
return s.DialOrDie().CoreV1().Services(ns).Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all Services in a given namespace.
|
||||
func (*Service) List(ns string) (Collection, error) {
|
||||
opts := metav1.ListOptions{}
|
||||
|
||||
rr, err := conn.dialOrDie().CoreV1().Services(ns).List(opts)
|
||||
func (s *Service) List(ns string) (Collection, error) {
|
||||
rr, err := s.DialOrDie().CoreV1().Services(ns).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return Collection{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc := make(Collection, len(rr.Items))
|
||||
for i, r := range rr.Items {
|
||||
cc[i] = r
|
||||
|
|
@ -36,7 +34,6 @@ func (*Service) List(ns string) (Collection, error) {
|
|||
}
|
||||
|
||||
// Delete a Service.
|
||||
func (*Service) Delete(ns, n string) error {
|
||||
opts := metav1.DeleteOptions{}
|
||||
return conn.dialOrDie().CoreV1().Services(ns).Delete(n, &opts)
|
||||
func (s *Service) Delete(ns, n string) error {
|
||||
return s.DialOrDie().CoreV1().Services(ns).Delete(n, nil)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue