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