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 }