github.com/kyma-project/kyma-environment-broker@v0.0.1/common/hyperscaler/shared_pool.go (about)

     1  package hyperscaler
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/kyma-project/kyma-environment-broker/common/gardener"
     8  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
     9  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    10  	"k8s.io/client-go/dynamic"
    11  )
    12  
    13  type SharedPool interface {
    14  	SharedCredentialsSecretBinding(hyperscalerType Type, euAccess bool) (*gardener.SecretBinding, error)
    15  }
    16  
    17  func NewSharedGardenerAccountPool(gardenerClient dynamic.Interface, gardenerNamespace string) SharedPool {
    18  	return &sharedAccountPool{
    19  		gardenerClient: gardenerClient,
    20  		namespace:      gardenerNamespace,
    21  	}
    22  }
    23  
    24  type sharedAccountPool struct {
    25  	gardenerClient dynamic.Interface
    26  	namespace      string
    27  }
    28  
    29  func (sp *sharedAccountPool) SharedCredentialsSecretBinding(hyperscalerType Type, euAccess bool) (*gardener.SecretBinding, error) {
    30  	labelSelector := fmt.Sprintf("shared=true,hyperscalerType=%s", hyperscalerType)
    31  	secretBindings, err := sp.getSecretBindings(labelSelector)
    32  	if err != nil {
    33  		return nil, fmt.Errorf("getting secret binding: %w", err)
    34  	}
    35  
    36  	return sp.getLeastUsed(secretBindings)
    37  }
    38  
    39  func (sp *sharedAccountPool) getSecretBindings(labelSelector string) ([]unstructured.Unstructured, error) {
    40  	secretBindings, err := sp.gardenerClient.Resource(gardener.SecretBindingResource).Namespace(sp.namespace).List(context.Background(), metav1.ListOptions{
    41  		LabelSelector: labelSelector,
    42  	})
    43  	if err != nil {
    44  		return nil, fmt.Errorf("error listing secret bindings for %s label selector: %w", labelSelector, err)
    45  	}
    46  
    47  	if secretBindings == nil || len(secretBindings.Items) == 0 {
    48  		return nil, fmt.Errorf("sharedAccountPool error: no shared secret binding found for %s label selector, "+
    49  			"namespace %s", labelSelector, sp.namespace)
    50  	}
    51  
    52  	return secretBindings.Items, nil
    53  }
    54  
    55  func (sp *sharedAccountPool) getLeastUsed(secretBindings []unstructured.Unstructured) (*gardener.SecretBinding, error) {
    56  	usageCount := make(map[string]int, len(secretBindings))
    57  	for _, s := range secretBindings {
    58  		usageCount[s.GetName()] = 0
    59  	}
    60  
    61  	shoots, err := sp.gardenerClient.Resource(gardener.ShootResource).Namespace(sp.namespace).List(context.Background(), metav1.ListOptions{})
    62  	if err != nil {
    63  		return nil, fmt.Errorf("error while listing Shoots: %w", err)
    64  	}
    65  
    66  	if shoots == nil || len(shoots.Items) == 0 {
    67  		return &gardener.SecretBinding{secretBindings[0]}, nil
    68  	}
    69  
    70  	for _, shoot := range shoots.Items {
    71  		s := gardener.Shoot{shoot}
    72  		count, found := usageCount[s.GetSpecSecretBindingName()]
    73  		if !found {
    74  			continue
    75  		}
    76  
    77  		usageCount[s.GetSpecSecretBindingName()] = count + 1
    78  	}
    79  
    80  	min := usageCount[secretBindings[0].GetName()]
    81  	minIndex := 0
    82  
    83  	for i, sb := range secretBindings {
    84  		if usageCount[sb.GetName()] < min {
    85  			min = usageCount[sb.GetName()]
    86  			minIndex = i
    87  		}
    88  	}
    89  
    90  	return &gardener.SecretBinding{secretBindings[minIndex]}, nil
    91  }