pkg/multiclusterclient/provider.go (64 lines of code) (raw):
package multiclusterclient
import (
"context"
"fmt"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"sigs.k8s.io/controller-runtime/pkg/client"
cdPipeApi "github.com/epam/edp-cd-pipeline-operator/v2/api/v1"
)
type ClientProvider struct {
internalClusterClient client.Client
}
// NewClientProvider creates a new ClientProvider instance.
func NewClientProvider(internalClusterClient client.Client) *ClientProvider {
return &ClientProvider{internalClusterClient: internalClusterClient}
}
func (c *ClientProvider) GetClusterClient(ctx context.Context, secretNamespace, clusterName string, options client.Options) (client.Client, error) {
if clusterName == "" || clusterName == cdPipeApi.InCluster {
return c.internalClusterClient, nil
}
secret, err := c.getClusterSecret(ctx, clusterName, secretNamespace)
if err != nil {
return nil, err
}
restConfig, err := ClusterSecretToRestConfig(secret)
if err != nil {
return nil, err
}
if options.Scheme == nil {
options.Scheme = c.internalClusterClient.Scheme()
}
cl, err := client.New(restConfig, options)
if err != nil {
return nil, fmt.Errorf("failed to create client: %w", err)
}
return cl, nil
}
func (c *ClientProvider) getClusterSecret(ctx context.Context, clusterName, secretNamespace string) (*corev1.Secret, error) {
secret := &corev1.Secret{}
if err := c.internalClusterClient.Get(
ctx,
client.ObjectKey{
Namespace: secretNamespace,
Name: clusterName,
},
secret,
); err != nil {
return nil, fmt.Errorf("failed to get cluster secret: %w", err)
}
return secret, nil
}
const k8sClientConfigQPS = 50
// ClusterSecretToRestConfig creates a rest.Config from the cluster secret.
func ClusterSecretToRestConfig(s *corev1.Secret) (*rest.Config, error) {
if _, ok := s.Data["config"]; !ok {
return nil, fmt.Errorf("no config data in the secret %s", s.Name)
}
config, err := clientcmd.RESTConfigFromKubeConfig(s.Data["config"])
if err != nil {
return nil, fmt.Errorf("failed to create rest config from cluster secret: %w", err)
}
config.QPS = k8sClientConfigQPS
config.Burst = int(config.QPS * 2)
return config, nil
}