pkg/kubeconfig/kubeconfig_writer.go (79 lines of code) (raw):
package kubeconfig
import (
"bytes"
"context"
"io"
"time"
corev1 "k8s.io/api/core/v1"
"github.com/aws/eks-anywhere/pkg/clients/kubernetes"
"github.com/aws/eks-anywhere/pkg/clusterapi"
"github.com/aws/eks-anywhere/pkg/constants"
"github.com/aws/eks-anywhere/pkg/retrier"
)
// ClientFactory builds Kubernetes clients.
type ClientFactory interface {
// BuildClientFromKubeconfig builds a Kubernetes client from a kubeconfig file.
BuildClientFromKubeconfig(kubeconfigPath string) (kubernetes.Client, error)
}
// ClusterAPIKubeconfigSecretWriter reads the kubeconfig secret on a cluster and copies the contents to a writer.
type ClusterAPIKubeconfigSecretWriter struct {
client ClientFactory
timeout time.Duration
backoff time.Duration
}
// WriterOpt allows to configure [KubeconfigWriter].
type WriterOpt func(*ClusterAPIKubeconfigSecretWriter)
// WithTimeout sets the optional timeout for a KubeconfigWriter.
func WithTimeout(timeout time.Duration) WriterOpt {
return func(writer *ClusterAPIKubeconfigSecretWriter) {
writer.timeout = timeout
}
}
// WithBackoff sets the optional backoff duration for a KubeconfigWriter.
func WithBackoff(backoff time.Duration) WriterOpt {
return func(writer *ClusterAPIKubeconfigSecretWriter) {
writer.backoff = backoff
}
}
// NewClusterAPIKubeconfigSecretWriter creates a ClusterAPIKubeconfigSecretWriter.
func NewClusterAPIKubeconfigSecretWriter(unauthClient ClientFactory, opts ...WriterOpt) ClusterAPIKubeconfigSecretWriter {
kr := &ClusterAPIKubeconfigSecretWriter{
client: unauthClient,
timeout: time.Minute,
backoff: time.Second,
}
for _, o := range opts {
o(kr)
}
return *kr
}
// WriteKubeconfig retrieves the contents of the specified cluster's kubeconfig from a secret and copies it to an io.Writer.
func (kr ClusterAPIKubeconfigSecretWriter) WriteKubeconfig(ctx context.Context, clusterName, kubeconfigPath string, w io.Writer) error {
rawKubeconfig, err := kr.GetClusterKubeconfig(ctx, clusterName, kubeconfigPath)
if err != nil {
return err
}
if err := kr.WriteKubeconfigContent(ctx, clusterName, rawKubeconfig, w); err != nil {
return err
}
return nil
}
// WriteKubeconfigContent copies a raw kubeconfig to an io.Writer.
func (kr ClusterAPIKubeconfigSecretWriter) WriteKubeconfigContent(ctx context.Context, clusterName string, content []byte, w io.Writer) error {
if _, err := io.Copy(w, bytes.NewReader(content)); err != nil {
return err
}
return nil
}
// GetClusterKubeconfig gets the cluster's kubeconfig from the secret.
func (kr ClusterAPIKubeconfigSecretWriter) GetClusterKubeconfig(ctx context.Context, clusterName, kubeconfigPath string) ([]byte, error) {
kubeconfigSecret := &corev1.Secret{}
var kubeClient kubernetes.Client
kubeClient, err := kr.client.BuildClientFromKubeconfig(kubeconfigPath)
if err != nil {
return nil, err
}
err = retrier.New(
kr.timeout,
retrier.WithRetryPolicy(retrier.BackOffPolicy(kr.backoff)),
).Retry(func() error {
if err = kubeClient.Get(ctx, clusterapi.ClusterKubeconfigSecretName(clusterName), constants.EksaSystemNamespace, kubeconfigSecret); err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return kubeconfigSecret.Data["value"], nil
}