Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 26 additions & 7 deletions serverscom/loadbalancers.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func newLoadBalancers(client *cli.Client, defaultLocationID *int64) cloudprovide
}

func (l *loadBalancers) GetLoadBalancer(ctx context.Context, clusterName string, service *v1.Service) (*v1.LoadBalancerStatus, bool, error) {
loadBalancer, err := l.findLoadBalancerByName(ctx, clusterName, service)
loadBalancer, err := l.findLoadBalancer(ctx, clusterName, service)

if err != nil && isNotFoundError(err) {
return nil, false, nil
Expand All @@ -59,7 +59,7 @@ func (l *loadBalancers) GetLoadBalancerName(ctx context.Context, clusterName str
}

func (l *loadBalancers) EnsureLoadBalancer(ctx context.Context, clusterName string, service *v1.Service, nodes []*v1.Node) (*v1.LoadBalancerStatus, error) {
loadBalancer, err := l.findLoadBalancerByName(ctx, clusterName, service)
loadBalancer, err := l.findLoadBalancer(ctx, clusterName, service)
if err != nil {
if !isNotFoundError(err) {
return nil, err
Expand Down Expand Up @@ -130,7 +130,7 @@ func (l *loadBalancers) EnsureLoadBalancer(ctx context.Context, clusterName stri
}

func (l *loadBalancers) UpdateLoadBalancer(ctx context.Context, clusterName string, service *v1.Service, nodes []*v1.Node) error {
loadBalancer, err := l.findLoadBalancerByName(ctx, clusterName, service)
loadBalancer, err := l.findLoadBalancer(ctx, clusterName, service)
if err != nil {
return err
}
Expand Down Expand Up @@ -166,7 +166,7 @@ func (l *loadBalancers) UpdateLoadBalancer(ctx context.Context, clusterName stri
}

func (l *loadBalancers) EnsureLoadBalancerDeleted(ctx context.Context, clusterName string, service *v1.Service) error {
loadBalancer, err := l.findLoadBalancerByName(ctx, clusterName, service)
loadBalancer, err := l.findLoadBalancer(ctx, clusterName, service)
if err != nil {
if isNotFoundError(err) {
return nil
Expand All @@ -178,10 +178,29 @@ func (l *loadBalancers) EnsureLoadBalancerDeleted(ctx context.Context, clusterNa
return l.client.LoadBalancers.DeleteL4LoadBalancer(ctx, loadBalancer.ID)
}

func (l *loadBalancers) findLoadBalancerByName(ctx context.Context, clusterName string, service *v1.Service) (*cli.L4LoadBalancer, error) {
name := l.GetLoadBalancerName(ctx, clusterName, service)

// findLoadBalancer tries to find load balancer by label selector first, then by name
func (l *loadBalancers) findLoadBalancer(ctx context.Context, clusterName string, service *v1.Service) (*cli.L4LoadBalancer, error) {
// first try to find by label selector
labelSelector := loadBalancerServiceUUIDLabel + "=" + string(service.UID)
loadBalancers, err := l.client.LoadBalancers.Collection().
SetPerPage(100).
SetParam(typeParamKey, "l4").
SetParam("label_selector", labelSelector).
Collect(ctx)

if err != nil {
return nil, err
}

if len(loadBalancers) == 1 {
return l.client.LoadBalancers.GetL4LoadBalancer(ctx, loadBalancers[0].ID)
} else if len(loadBalancers) > 1 {
return nil, fmt.Errorf("found more than one load balancer with the same label selector: %s", labelSelector)
}

// fallback to name-based search
name := l.GetLoadBalancerName(ctx, clusterName, service)
loadBalancers, err = l.client.LoadBalancers.Collection().
SetPerPage(100).
SetParam(typeParamKey, "l4").
SetParam(searchPatternParamKey, name).
Expand Down
107 changes: 90 additions & 17 deletions serverscom/loadbalancers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,18 @@ func TestLoadBalancers_GetLoadBalancer(t *testing.T) {

ctx := context.TODO()

// First search by label_selector (should return empty)
collection.EXPECT().SetPerPage(100).Return(collection)
collection.EXPECT().SetParam("search_pattern", balancerName).Return(collection)
collection.EXPECT().SetParam("type", "l4").Return(collection)
collection.EXPECT().SetParam("label_selector", "k8s.servers.com/service-id=123").Return(collection)
collection.EXPECT().Collect(ctx).Return([]cli.LoadBalancer{}, nil)

service.EXPECT().Collection().Return(collection)

// Second search by name
collection.EXPECT().SetPerPage(100).Return(collection)
collection.EXPECT().SetParam("type", "l4").Return(collection)
collection.EXPECT().SetParam("search_pattern", balancerName).Return(collection)
collection.EXPECT().Collect(ctx).Return([]cli.LoadBalancer{balancer}, nil)

service.EXPECT().Collection().Return(collection)
Expand Down Expand Up @@ -81,9 +90,18 @@ func TestLoadBalancers_GetLoadBalancerNonActive(t *testing.T) {

ctx := context.TODO()

// First search by label_selector (should return empty)
collection.EXPECT().SetPerPage(100).Return(collection)
collection.EXPECT().SetParam("search_pattern", balancerName).Return(collection)
collection.EXPECT().SetParam("type", "l4").Return(collection)
collection.EXPECT().SetParam("label_selector", "k8s.servers.com/service-id=123").Return(collection)
collection.EXPECT().Collect(ctx).Return([]cli.LoadBalancer{}, nil)

service.EXPECT().Collection().Return(collection)

// Second search by name
collection.EXPECT().SetPerPage(100).Return(collection)
collection.EXPECT().SetParam("type", "l4").Return(collection)
collection.EXPECT().SetParam("search_pattern", balancerName).Return(collection)
collection.EXPECT().Collect(ctx).Return([]cli.LoadBalancer{balancer}, nil)

service.EXPECT().Collection().Return(collection)
Expand Down Expand Up @@ -118,9 +136,18 @@ func TestLoadBalancers_GetLoadBalancerEmptyList(t *testing.T) {

ctx := context.TODO()

// First search by label_selector (should return empty)
collection.EXPECT().SetPerPage(100).Return(collection)
collection.EXPECT().SetParam("search_pattern", balancerName).Return(collection)
collection.EXPECT().SetParam("type", "l4").Return(collection)
collection.EXPECT().SetParam("label_selector", "k8s.servers.com/service-id=123").Return(collection)
collection.EXPECT().Collect(ctx).Return([]cli.LoadBalancer{}, nil)

service.EXPECT().Collection().Return(collection)

// Second search by name (should return empty)
collection.EXPECT().SetPerPage(100).Return(collection)
collection.EXPECT().SetParam("type", "l4").Return(collection)
collection.EXPECT().SetParam("search_pattern", balancerName).Return(collection)
collection.EXPECT().Collect(ctx).Return([]cli.LoadBalancer{}, nil)

service.EXPECT().Collection().Return(collection)
Expand Down Expand Up @@ -254,9 +281,10 @@ func TestLoadBalancers_EnsureLoadBalancer(t *testing.T) {
Labels: defaultLabels,
}

// First search by label_selector (should find the balancer)
collection.EXPECT().SetPerPage(100).Return(collection)
collection.EXPECT().SetParam("search_pattern", balancerName).Return(collection)
collection.EXPECT().SetParam("type", "l4").Return(collection)
collection.EXPECT().SetParam("label_selector", "k8s.servers.com/service-id=123").Return(collection)
collection.EXPECT().Collect(ctx).Return([]cli.LoadBalancer{balancer}, nil)

service.EXPECT().Collection().Return(collection)
Expand Down Expand Up @@ -362,12 +390,21 @@ func TestLoadBalancers_EnsureLoadBalancerWithCreate(t *testing.T) {
Labels: defaultLabels,
}

collection.EXPECT().SetPerPage(100).Return(collection).Times(2)
collection.EXPECT().SetParam("search_pattern", balancerName).Return(collection).Times(2)
collection.EXPECT().SetParam("type", "l4").Return(collection).Times(2)
collection.EXPECT().Collect(ctx).Return([]cli.LoadBalancer{}, nil).Times(2)
// First search by label_selector (should return empty)
collection.EXPECT().SetPerPage(100).Return(collection)
collection.EXPECT().SetParam("type", "l4").Return(collection)
collection.EXPECT().SetParam("label_selector", "k8s.servers.com/service-id=123").Return(collection)
collection.EXPECT().Collect(ctx).Return([]cli.LoadBalancer{}, nil)

service.EXPECT().Collection().Return(collection)

// Second search by name (should return empty)
collection.EXPECT().SetPerPage(100).Return(collection)
collection.EXPECT().SetParam("type", "l4").Return(collection)
collection.EXPECT().SetParam("search_pattern", balancerName).Return(collection)
collection.EXPECT().Collect(ctx).Return([]cli.LoadBalancer{}, nil)

service.EXPECT().Collection().Return(collection).Times(2)
service.EXPECT().Collection().Return(collection)
service.EXPECT().CreateL4LoadBalancer(ctx, input).Return(&l4Balancer, nil)

client := cli.NewClient("some")
Expand Down Expand Up @@ -400,6 +437,22 @@ func TestLoadBalancers_EnsureLoadBalancerWithCreate(t *testing.T) {
}

input.ClusterID = &clusterID

// First search by label_selector (should return empty)
collection.EXPECT().SetPerPage(100).Return(collection)
collection.EXPECT().SetParam("type", "l4").Return(collection)
collection.EXPECT().SetParam("label_selector", "k8s.servers.com/service-id=123").Return(collection)
collection.EXPECT().Collect(ctx).Return([]cli.LoadBalancer{}, nil)

service.EXPECT().Collection().Return(collection)

// Second search by name (should return empty)
collection.EXPECT().SetPerPage(100).Return(collection)
collection.EXPECT().SetParam("type", "l4").Return(collection)
collection.EXPECT().SetParam("search_pattern", balancerName).Return(collection)
collection.EXPECT().Collect(ctx).Return([]cli.LoadBalancer{}, nil)

service.EXPECT().Collection().Return(collection)
service.EXPECT().CreateL4LoadBalancer(ctx, input).Return(&l4Balancer, nil)
status, err = balancerInterface.EnsureLoadBalancer(ctx, "cluster", &srv, []*v1.Node{&node})

Expand Down Expand Up @@ -488,13 +541,14 @@ func TestLoadBalancers_UpdateLoadBalancer(t *testing.T) {
Labels: defaultLabels,
}

collection.EXPECT().SetPerPage(100).Return(collection).Times(2)
collection.EXPECT().SetParam("search_pattern", balancerName).Return(collection).Times(2)
collection.EXPECT().SetParam("type", "l4").Return(collection).Times(2)
collection.EXPECT().Collect(ctx).Return([]cli.LoadBalancer{balancer}, nil).Times(2)
// First call: search by label_selector (should find the balancer)
collection.EXPECT().SetPerPage(100).Return(collection)
collection.EXPECT().SetParam("type", "l4").Return(collection)
collection.EXPECT().SetParam("label_selector", "k8s.servers.com/service-id=123").Return(collection)
collection.EXPECT().Collect(ctx).Return([]cli.LoadBalancer{balancer}, nil)

service.EXPECT().Collection().Return(collection).Times(2)
service.EXPECT().GetL4LoadBalancer(ctx, "a").Return(&l4Balancer, nil).Times(2)
service.EXPECT().Collection().Return(collection)
service.EXPECT().GetL4LoadBalancer(ctx, "a").Return(&l4Balancer, nil)
service.EXPECT().UpdateL4LoadBalancer(ctx, "a", input).Return(&l4Balancer, nil)

client := cli.NewClient("some")
Expand Down Expand Up @@ -528,6 +582,15 @@ func TestLoadBalancers_UpdateLoadBalancer(t *testing.T) {

input.ClusterID = &clusterID
input.SharedCluster = nil

// Second call: search by label_selector (should find the balancer)
collection.EXPECT().SetPerPage(100).Return(collection)
collection.EXPECT().SetParam("type", "l4").Return(collection)
collection.EXPECT().SetParam("label_selector", "k8s.servers.com/service-id=123").Return(collection)
collection.EXPECT().Collect(ctx).Return([]cli.LoadBalancer{balancer}, nil)

service.EXPECT().Collection().Return(collection)
service.EXPECT().GetL4LoadBalancer(ctx, "a").Return(&l4Balancer, nil)
service.EXPECT().UpdateL4LoadBalancer(ctx, "a", input).Return(&l4Balancer, nil)
status, err = balancerInterface.EnsureLoadBalancer(ctx, "cluster", &srv, []*v1.Node{&node})

Expand All @@ -553,9 +616,10 @@ func TestLoadBalancers_EnsureLoadBalancerDeleted(t *testing.T) {

ctx := context.TODO()

// First search by label_selector (should find the balancer)
collection.EXPECT().SetPerPage(100).Return(collection)
collection.EXPECT().SetParam("search_pattern", balancerName).Return(collection)
collection.EXPECT().SetParam("type", "l4").Return(collection)
collection.EXPECT().SetParam("label_selector", "k8s.servers.com/service-id=123").Return(collection)
collection.EXPECT().Collect(ctx).Return([]cli.LoadBalancer{balancer}, nil)

service.EXPECT().Collection().Return(collection)
Expand Down Expand Up @@ -591,9 +655,18 @@ func TestLoadBalancers_EnsureLoadBalancerDeletedWhenBalancerAlreadyDeleted(t *te

ctx := context.TODO()

// First search by label_selector (should return empty)
collection.EXPECT().SetPerPage(100).Return(collection)
collection.EXPECT().SetParam("type", "l4").Return(collection)
collection.EXPECT().SetParam("label_selector", "k8s.servers.com/service-id=123").Return(collection)
collection.EXPECT().Collect(ctx).Return([]cli.LoadBalancer{}, nil)

service.EXPECT().Collection().Return(collection)

// Second search by name (should return empty)
collection.EXPECT().SetPerPage(100).Return(collection)
collection.EXPECT().SetParam("search_pattern", balancerName).Return(collection)
collection.EXPECT().SetParam("type", "l4").Return(collection)
collection.EXPECT().SetParam("search_pattern", balancerName).Return(collection)
collection.EXPECT().Collect(ctx).Return([]cli.LoadBalancer{}, nil)

service.EXPECT().Collection().Return(collection)
Expand Down