Skip to content

Commit

Permalink
Merge pull request #16295 from justinsb/refactor_list_elbv2_loadbalan…
Browse files Browse the repository at this point in the history
…cers

Refactor: Move NLB listing function into awsup
  • Loading branch information
k8s-ci-robot authored Jan 30, 2024
2 parents ffbcc52 + 314e2b9 commit d4bdc68
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 61 deletions.
6 changes: 6 additions & 0 deletions cloudmock/aws/mockelbv2/loadbalancers.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ limitations under the License.
package mockelbv2

import (
"context"
"fmt"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/elbv2"
"k8s.io/klog/v2"
Expand Down Expand Up @@ -74,6 +76,10 @@ func (m *MockELBV2) DescribeLoadBalancersPages(request *elbv2.DescribeLoadBalanc
return nil
}

func (m *MockELBV2) DescribeLoadBalancersPagesWithContext(ctx context.Context, request *elbv2.DescribeLoadBalancersInput, callback func(p *elbv2.DescribeLoadBalancersOutput, lastPage bool) (shouldContinue bool), opts ...request.Option) error {
return m.DescribeLoadBalancersPages(request, callback)
}

func (m *MockELBV2) CreateLoadBalancer(request *elbv2.CreateLoadBalancerInput) (*elbv2.CreateLoadBalancerOutput, error) {
m.mutex.Lock()
defer m.mutex.Unlock()
Expand Down
66 changes: 5 additions & 61 deletions pkg/resources/aws/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -1568,13 +1568,16 @@ func DescribeELBs(cloud fi.Cloud) ([]*elb.LoadBalancerDescription, map[string][]

// For NLBs and ALBs
func ListELBV2s(cloud fi.Cloud, vpcID, clusterName string) ([]*resources.Resource, error) {
elbv2s, _, err := DescribeELBV2s(cloud)
ctx := context.TODO()

loadBalancers, err := awsup.ListELBV2LoadBalancers(ctx, cloud.(awsup.AWSCloud))
if err != nil {
return nil, err
}

var resourceTrackers []*resources.Resource
for _, elb := range elbv2s {
for _, loadBalancer := range loadBalancers {
elb := loadBalancer.LoadBalancer
id := aws.StringValue(elb.LoadBalancerName)
resourceTracker := &resources.Resource{
Name: id,
Expand All @@ -1600,65 +1603,6 @@ func ListELBV2s(cloud fi.Cloud, vpcID, clusterName string) ([]*resources.Resourc
return resourceTrackers, nil
}

func DescribeELBV2s(cloud fi.Cloud) ([]*elbv2.LoadBalancer, map[string][]*elbv2.Tag, error) {
c := cloud.(awsup.AWSCloud)
tags := c.Tags()

klog.V(2).Infof("Listing all NLBs and ALBs")

request := &elbv2.DescribeLoadBalancersInput{}
// ELBV2 DescribeTags has a limit of 20 names, so we set the page size here to 20 also
request.PageSize = aws.Int64(20)

var elbv2s []*elbv2.LoadBalancer
elbv2Tags := make(map[string][]*elbv2.Tag)

var innerError error
err := c.ELBV2().DescribeLoadBalancersPages(request, func(p *elbv2.DescribeLoadBalancersOutput, lastPage bool) bool {
if len(p.LoadBalancers) == 0 {
return true
}

tagRequest := &elbv2.DescribeTagsInput{}

nameToELB := make(map[string]*elbv2.LoadBalancer)
for _, elb := range p.LoadBalancers {
name := aws.StringValue(elb.LoadBalancerArn)
nameToELB[name] = elb

tagRequest.ResourceArns = append(tagRequest.ResourceArns, elb.LoadBalancerArn)
}

tagResponse, err := c.ELBV2().DescribeTags(tagRequest)
if err != nil {
innerError = fmt.Errorf("error listing elb Tags: %v", err)
return false
}

for _, t := range tagResponse.TagDescriptions {

elbARN := aws.StringValue(t.ResourceArn)
if !matchesElbV2Tags(tags, t.Tags) {
continue
}

elbv2Tags[elbARN] = t.Tags
elb := nameToELB[elbARN]
elbv2s = append(elbv2s, elb)
}

return true
})
if err != nil {
return nil, nil, fmt.Errorf("error describing LoadBalancers: %v", err)
}
if innerError != nil {
return nil, nil, fmt.Errorf("error describing LoadBalancers: %v", innerError)
}

return elbv2s, elbv2Tags, nil
}

func DumpTargetGroup(op *resources.DumpOperation, r *resources.Resource) error {
data := make(map[string]interface{})
data["id"] = r.ID
Expand Down
2 changes: 2 additions & 0 deletions upup/pkg/fi/cloudup/awsup/aws_cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,9 @@ type AWSCloud interface {
RemoveELBV2Tags(ResourceArn string, tags map[string]string) error
FindELBByNameTag(findNameTag string) (*elb.LoadBalancerDescription, error)
DescribeELBTags(loadBalancerNames []string) (map[string][]*elb.Tag, error)
// TODO: Remove, replace with awsup.ListELBV2LoadBalancers
FindELBV2ByNameTag(findNameTag string) (*elbv2.LoadBalancer, error)
// TODO: Remove, replace with awsup.ListELBV2LoadBalancers
DescribeELBV2Tags(loadBalancerNames []string) (map[string][]*elbv2.Tag, error)
FindELBV2NetworkInterfacesByName(vpcID string, loadBalancerName string) ([]*ec2.NetworkInterface, error)

Expand Down
136 changes: 136 additions & 0 deletions upup/pkg/fi/cloudup/awsup/elbv2_loadbalancers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
Copyright 2024 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package awsup

import (
"context"
"errors"
"fmt"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/elbv2"
"k8s.io/klog/v2"
)

type LoadBalancerInfo struct {
LoadBalancer *elbv2.LoadBalancer
Tags []*elbv2.Tag
}

// ARN returns the ARN of the load balancer.
func (i *LoadBalancerInfo) ARN() string {
return aws.StringValue(i.LoadBalancer.LoadBalancerArn)
}

// NameTag returns the value of the tag with the key "Name".
func (i *LoadBalancerInfo) NameTag() string {
s, _ := i.GetTag("Name")
return s
}

// GetTag returns the value of the tag with the given key.
func (i *LoadBalancerInfo) GetTag(key string) (string, bool) {
for _, tag := range i.Tags {
if aws.StringValue(tag.Key) == key {
return aws.StringValue(tag.Value), true
}
}
return "", false
}

func ListELBV2LoadBalancers(ctx context.Context, cloud AWSCloud) ([]*LoadBalancerInfo, error) {
// TODO: Any way around this?
klog.V(2).Infof("Listing all NLBs for ListELBV2LoadBalancers")

request := &elbv2.DescribeLoadBalancersInput{}
// ELBV2 DescribeTags has a limit of 20 names, so we set the page size here to 20 also
request.PageSize = aws.Int64(20)

byARN := make(map[string]*LoadBalancerInfo)

var errs []error
err := cloud.ELBV2().DescribeLoadBalancersPagesWithContext(ctx, request, func(p *elbv2.DescribeLoadBalancersOutput, lastPage bool) bool {
if len(p.LoadBalancers) == 0 {
return true
}

tagRequest := &elbv2.DescribeTagsInput{}

for _, elb := range p.LoadBalancers {
arn := aws.StringValue(elb.LoadBalancerArn)
byARN[arn] = &LoadBalancerInfo{LoadBalancer: elb}

// TODO: Any way to filter by cluster here?

tagRequest.ResourceArns = append(tagRequest.ResourceArns, elb.LoadBalancerArn)
}

tagResponse, err := cloud.ELBV2().DescribeTags(tagRequest)
if err != nil {
errs = append(errs, fmt.Errorf("listing ELB tags: %w", err))
return false
}

for _, t := range tagResponse.TagDescriptions {
arn := aws.StringValue(t.ResourceArn)

info := byARN[arn]
if info == nil {
klog.Fatalf("found tag for load balancer we didn't ask for %q", arn)
}

info.Tags = append(info.Tags, t.Tags...)
}

return true
})
if err != nil {
return nil, fmt.Errorf("listing ELB LoadBalancers: %w", err)
}
if len(errs) != 0 {
return nil, fmt.Errorf("listing ELB LoadBalancers: %w", errors.Join(errs...))
}

cloudTags := cloud.Tags()

var results []*LoadBalancerInfo
for _, v := range byARN {
if !MatchesElbV2Tags(cloudTags, v.Tags) {
continue
}
results = append(results, v)
}
return results, nil
}

func MatchesElbV2Tags(tags map[string]string, actual []*elbv2.Tag) bool {
for k, v := range tags {
found := false
for _, a := range actual {
if aws.StringValue(a.Key) == k {
if aws.StringValue(a.Value) == v {
found = true
break
}
}
}
if !found {
return false
}
}
return true
}

0 comments on commit d4bdc68

Please sign in to comment.