Skip to content

Commit

Permalink
Added GetClusterName function to get name from kubeconfig (#163)
Browse files Browse the repository at this point in the history
Signed-off-by: Marcus Noble <github@marcusnoble.co.uk>
  • Loading branch information
AverageMarcus committed Apr 2, 2024
1 parent 8dd44aa commit 75bf889
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 6 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Added a `GetClusterName` function that returns the friendly name of the cluster from the kubeconfig

## [0.16.0] - 2024-03-11

### Added
Expand Down
60 changes: 54 additions & 6 deletions pkg/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"net"
"net/url"
"os"
"reflect"
"strings"

Expand Down Expand Up @@ -34,7 +35,8 @@ import (
type Client struct {
cr.Client

config *rest.Config
config *rest.Config
clusterName string
}

// New creates a new Kubernetes client for the provided kubeconfig file
Expand All @@ -52,6 +54,10 @@ func New(kubeconfigPath string) (*Client, error) {
// The creation of the client doesn't confirm connectivity to the cluster and REST discovery is set to lazy discovery
// so the client can be created while the cluster is still being set up.
func NewFromRawKubeconfig(kubeconfig string) (*Client, error) {
clusterName, err := getClusterNameFromKubeConfig([]byte(kubeconfig), "")
if err != nil {
return nil, fmt.Errorf("failed to get cluster name - %v", err)
}
clientConfig, err := clientcmd.NewClientConfigFromBytes([]byte(kubeconfig))
if err != nil {
return nil, fmt.Errorf("failed to create config - %v", err)
Expand All @@ -61,7 +67,7 @@ func NewFromRawKubeconfig(kubeconfig string) (*Client, error) {
return nil, fmt.Errorf("failed to create rest config - %v", err)
}

return newClient(restConfig)
return newClient(restConfig, clusterName)
}

// NewFromSecret create a new Kubernetes client from a cluster kubeconfig found in a secret on the MC.
Expand Down Expand Up @@ -89,6 +95,12 @@ func NewWithContext(kubeconfigPath string, contextName string) (*Client, error)
return nil, fmt.Errorf("a kubeconfig file must be provided")
}

data, _ := os.ReadFile(kubeconfigPath)
clusterName, err := getClusterNameFromKubeConfig(data, contextName)
if err != nil {
return nil, fmt.Errorf("failed to get cluster name - %v", err)
}

cfg, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeconfigPath},
&clientcmd.ConfigOverrides{
Expand All @@ -99,10 +111,10 @@ func NewWithContext(kubeconfigPath string, contextName string) (*Client, error)
return nil, fmt.Errorf("failed to create config - %v", err)
}

return newClient(cfg)
return newClient(cfg, clusterName)
}

func newClient(config *rest.Config) (*Client, error) {
func newClient(config *rest.Config, clusterName string) (*Client, error) {
mapper, err := apiutil.NewDynamicRESTMapper(config, apiutil.WithLazyDiscovery)
if err != nil {
return nil, fmt.Errorf("failed to create new dynamic client - %v", err)
Expand All @@ -120,11 +132,42 @@ func newClient(config *rest.Config) (*Client, error) {
_ = kubeadm.AddToScheme(client.Scheme())

return &Client{
Client: client,
config: config,
Client: client,
config: config,
clusterName: clusterName,
}, nil
}

// getClusterNameFromKubeConfig gets the cluster name of the cluster selected for the provided context.
// The cluster name is the human-friendly name found in the KubeConfig.
// If an empty `contextName` is provided it will use the `CurrentContext` from the provided KubeConfig.
func getClusterNameFromKubeConfig(data []byte, contextName string) (string, error) {
if len(data) == 0 {
return "", fmt.Errorf("Empty kubeconfig provided")
}

kubeconfig := clientcmdapi.Config{}
err := yaml.Unmarshal(data, &kubeconfig)
if err != nil {
return "", err
}

// Default to the context in the kubeconfig if not provided
if contextName == "" {
contextName = kubeconfig.CurrentContext
}

clusterName := ""
for _, context := range kubeconfig.Contexts {
if context.Name == contextName {
clusterName = context.Context.Cluster
break
}
}

return clusterName, nil
}

// CheckConnection attempts to connect to the clusters API server and returns an error if not successful.
// A successful connection is defined as a valid response from the api-server but not necessarily a success response.
// For example, both a "Not Found" and a "Forbidden" response from the server is still a valid, working connection to
Expand Down Expand Up @@ -312,3 +355,8 @@ func (c *Client) DeleteApp(ctx context.Context, app application.Application) err
func (c *Client) GetAPIServerEndpoint() string {
return c.config.Host
}

// GetClusterName returns the friendly name of the Cluster from the KubeConfig
func (c *Client) GetClusterName() string {
return c.clusterName
}

0 comments on commit 75bf889

Please sign in to comment.