Migrate ELB to aws-sdk-go-v2

This commit is contained in:
Peter Rifel 2024-03-30 07:54:49 -05:00
parent 1d51354a1f
commit 2626a354c5
No known key found for this signature in database
15 changed files with 296 additions and 273 deletions

View File

@ -17,20 +17,22 @@ limitations under the License.
package mockelb
import (
"context"
"fmt"
"sync"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go/service/elb/elbiface"
"github.com/aws/aws-sdk-go-v2/aws"
elb "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing"
elbtypes "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing/types"
"k8s.io/klog/v2"
"k8s.io/kops/util/pkg/awsinterfaces"
)
const elbZoneID = "FAKEZONE-CLOUDMOCK-ELB"
type MockELB struct {
elbiface.ELBAPI
awsinterfaces.ELBAPI
mutex sync.Mutex
@ -38,12 +40,12 @@ type MockELB struct {
}
type loadBalancer struct {
description elb.LoadBalancerDescription
attributes elb.LoadBalancerAttributes
description elbtypes.LoadBalancerDescription
attributes elbtypes.LoadBalancerAttributes
tags map[string]string
}
func (m *MockELB) DescribeLoadBalancers(request *elb.DescribeLoadBalancersInput) (*elb.DescribeLoadBalancersOutput, error) {
func (m *MockELB) DescribeLoadBalancers(ctx context.Context, request *elb.DescribeLoadBalancersInput, optFns ...func(*elb.Options)) (*elb.DescribeLoadBalancersOutput, error) {
m.mutex.Lock()
defer m.mutex.Unlock()
@ -56,13 +58,13 @@ func (m *MockELB) DescribeLoadBalancers(request *elb.DescribeLoadBalancersInput)
klog.Fatalf("Marker not implemented")
}
var elbs []*elb.LoadBalancerDescription
var elbs []elbtypes.LoadBalancerDescription
for _, elb := range m.LoadBalancers {
match := false
if len(request.LoadBalancerNames) > 0 {
for _, name := range request.LoadBalancerNames {
if aws.StringValue(elb.description.LoadBalancerName) == aws.StringValue(name) {
if aws.ToString(elb.description.LoadBalancerName) == name {
match = true
}
}
@ -71,7 +73,7 @@ func (m *MockELB) DescribeLoadBalancers(request *elb.DescribeLoadBalancersInput)
}
if match {
elbs = append(elbs, &elb.description)
elbs = append(elbs, elb.description)
}
}
@ -80,19 +82,7 @@ func (m *MockELB) DescribeLoadBalancers(request *elb.DescribeLoadBalancersInput)
}, nil
}
func (m *MockELB) DescribeLoadBalancersPages(request *elb.DescribeLoadBalancersInput, callback func(p *elb.DescribeLoadBalancersOutput, lastPage bool) (shouldContinue bool)) error {
// For the mock, we just send everything in one page
page, err := m.DescribeLoadBalancers(request)
if err != nil {
return err
}
callback(page, false)
return nil
}
func (m *MockELB) CreateLoadBalancer(request *elb.CreateLoadBalancerInput) (*elb.CreateLoadBalancerOutput, error) {
func (m *MockELB) CreateLoadBalancer(ctx context.Context, request *elb.CreateLoadBalancerInput, optFns ...func(*elb.Options)) (*elb.CreateLoadBalancerOutput, error) {
m.mutex.Lock()
defer m.mutex.Unlock()
@ -102,7 +92,7 @@ func (m *MockELB) CreateLoadBalancer(request *elb.CreateLoadBalancerInput) (*elb
dnsName := *request.LoadBalancerName + ".elb.cloudmock.com"
lb := &loadBalancer{
description: elb.LoadBalancerDescription{
description: elbtypes.LoadBalancerDescription{
AvailabilityZones: request.AvailabilityZones,
CreatedTime: &createdTime,
LoadBalancerName: request.LoadBalancerName,
@ -117,8 +107,8 @@ func (m *MockELB) CreateLoadBalancer(request *elb.CreateLoadBalancerInput) (*elb
}
for _, listener := range request.Listeners {
lb.description.ListenerDescriptions = append(lb.description.ListenerDescriptions, &elb.ListenerDescription{
Listener: listener,
lb.description.ListenerDescriptions = append(lb.description.ListenerDescriptions, elbtypes.ListenerDescription{
Listener: &listener,
})
}
@ -142,13 +132,13 @@ func (m *MockELB) CreateLoadBalancer(request *elb.CreateLoadBalancerInput) (*elb
}, nil
}
func (m *MockELB) DeleteLoadBalancer(request *elb.DeleteLoadBalancerInput) (*elb.DeleteLoadBalancerOutput, error) {
func (m *MockELB) DeleteLoadBalancer(ctx context.Context, request *elb.DeleteLoadBalancerInput, optFns ...func(*elb.Options)) (*elb.DeleteLoadBalancerOutput, error) {
m.mutex.Lock()
defer m.mutex.Unlock()
klog.Infof("DeleteLoadBalancer: %v", request)
id := aws.StringValue(request.LoadBalancerName)
id := aws.ToString(request.LoadBalancerName)
o := m.LoadBalancers[id]
if o == nil {
return nil, fmt.Errorf("LoadBalancer %q not found", id)

View File

@ -17,20 +17,21 @@ limitations under the License.
package mockelb
import (
"context"
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go-v2/aws"
elb "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing"
"k8s.io/klog/v2"
)
func (m *MockELB) ModifyLoadBalancerAttributes(request *elb.ModifyLoadBalancerAttributesInput) (*elb.ModifyLoadBalancerAttributesOutput, error) {
func (m *MockELB) ModifyLoadBalancerAttributes(ctx context.Context, request *elb.ModifyLoadBalancerAttributesInput, optFns ...func(*elb.Options)) (*elb.ModifyLoadBalancerAttributesOutput, error) {
m.mutex.Lock()
defer m.mutex.Unlock()
klog.Infof("ModifyLoadBalancerAttributes: %v", request)
lb := m.LoadBalancers[aws.StringValue(request.LoadBalancerName)]
lb := m.LoadBalancers[aws.ToString(request.LoadBalancerName)]
if lb == nil {
return nil, fmt.Errorf("LoadBalancer not found")
}
@ -45,13 +46,13 @@ func (m *MockELB) ModifyLoadBalancerAttributes(request *elb.ModifyLoadBalancerAt
}, nil
}
func (m *MockELB) DescribeLoadBalancerAttributes(request *elb.DescribeLoadBalancerAttributesInput) (*elb.DescribeLoadBalancerAttributesOutput, error) {
func (m *MockELB) DescribeLoadBalancerAttributes(ctx context.Context, request *elb.DescribeLoadBalancerAttributesInput, optFns ...func(*elb.Options)) (*elb.DescribeLoadBalancerAttributesOutput, error) {
m.mutex.Lock()
defer m.mutex.Unlock()
klog.Infof("DescribeLoadBalancerAttributes: %v", request)
lb := m.LoadBalancers[aws.StringValue(request.LoadBalancerName)]
lb := m.LoadBalancers[aws.ToString(request.LoadBalancerName)]
if lb == nil {
return nil, fmt.Errorf("LoadBalancer not found")
}

View File

@ -17,20 +17,21 @@ limitations under the License.
package mockelb
import (
"context"
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go-v2/aws"
elb "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing"
"k8s.io/klog/v2"
)
func (m *MockELB) ConfigureHealthCheck(request *elb.ConfigureHealthCheckInput) (*elb.ConfigureHealthCheckOutput, error) {
func (m *MockELB) ConfigureHealthCheck(ctx context.Context, request *elb.ConfigureHealthCheckInput, optFns ...func(*elb.Options)) (*elb.ConfigureHealthCheckOutput, error) {
m.mutex.Lock()
defer m.mutex.Unlock()
klog.Infof("ConfigureHealthCheck: %v", request)
lb := m.LoadBalancers[aws.StringValue(request.LoadBalancerName)]
lb := m.LoadBalancers[aws.ToString(request.LoadBalancerName)]
if lb == nil {
return nil, fmt.Errorf("LoadBalancer not found")
}

View File

@ -20,23 +20,19 @@ 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/elb"
"github.com/aws/aws-sdk-go-v2/aws"
elb "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing"
elbtypes "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing/types"
"k8s.io/klog/v2"
)
func (m *MockELB) DescribeTags(request *elb.DescribeTagsInput) (*elb.DescribeTagsOutput, error) {
return m.DescribeTagsWithContext(context.TODO(), request)
}
func (m *MockELB) DescribeTagsWithContext(ctx aws.Context, request *elb.DescribeTagsInput, opt ...request.Option) (*elb.DescribeTagsOutput, error) {
func (m *MockELB) DescribeTags(ctx context.Context, request *elb.DescribeTagsInput, optFns ...func(*elb.Options)) (*elb.DescribeTagsOutput, error) {
m.mutex.Lock()
defer m.mutex.Unlock()
klog.Infof("DescribeTags %v", request)
var tags []*elb.TagDescription
var tags []elbtypes.TagDescription
for k, lb := range m.LoadBalancers {
match := false
@ -44,7 +40,7 @@ func (m *MockELB) DescribeTagsWithContext(ctx aws.Context, request *elb.Describe
match = true
} else {
for _, name := range request.LoadBalancerNames {
if *name == k {
if name == k {
match = true
}
}
@ -54,11 +50,11 @@ func (m *MockELB) DescribeTagsWithContext(ctx aws.Context, request *elb.Describe
continue
}
tagDescription := &elb.TagDescription{
tagDescription := elbtypes.TagDescription{
LoadBalancerName: aws.String(k),
}
for k, v := range lb.tags {
tagDescription.Tags = append(tagDescription.Tags, &elb.Tag{
tagDescription.Tags = append(tagDescription.Tags, elbtypes.Tag{
Key: aws.String(k),
Value: aws.String(v),
})
@ -73,16 +69,16 @@ func (m *MockELB) DescribeTagsWithContext(ctx aws.Context, request *elb.Describe
return response, nil
}
func (m *MockELB) AddTags(request *elb.AddTagsInput) (*elb.AddTagsOutput, error) {
func (m *MockELB) AddTags(ctx context.Context, request *elb.AddTagsInput, optFns ...func(*elb.Options)) (*elb.AddTagsOutput, error) {
m.mutex.Lock()
defer m.mutex.Unlock()
klog.Infof("AddTags %v", request)
for _, name := range request.LoadBalancerNames {
elb := m.LoadBalancers[*name]
elb := m.LoadBalancers[name]
if elb == nil {
return nil, fmt.Errorf("ELB %q not found", *name)
return nil, fmt.Errorf("ELB %q not found", name)
}
for _, tag := range request.Tags {
elb.tags[*tag.Key] = *tag.Value

View File

@ -232,19 +232,19 @@ func (b *APILoadBalancerBuilder) Build(c *fi.CloudupModelBuilderContext) error {
// Configure fast-recovery health-checks
HealthCheck: &awstasks.ClassicLoadBalancerHealthCheck{
Target: fi.PtrTo("SSL:443"),
Timeout: fi.PtrTo(int64(5)),
Interval: fi.PtrTo(int64(10)),
HealthyThreshold: fi.PtrTo(int64(2)),
UnhealthyThreshold: fi.PtrTo(int64(2)),
Timeout: fi.PtrTo(int32(5)),
Interval: fi.PtrTo(int32(10)),
HealthyThreshold: fi.PtrTo(int32(2)),
UnhealthyThreshold: fi.PtrTo(int32(2)),
},
ConnectionSettings: &awstasks.ClassicLoadBalancerConnectionSettings{
IdleTimeout: fi.PtrTo(int64(idleTimeout.Seconds())),
IdleTimeout: fi.PtrTo(int32(idleTimeout.Seconds())),
},
ConnectionDraining: &awstasks.ClassicLoadBalancerConnectionDraining{
Enabled: fi.PtrTo(true),
Timeout: fi.PtrTo(int64(300)),
Timeout: fi.PtrTo(int32(300)),
},
Tags: tags,
@ -276,7 +276,7 @@ func (b *APILoadBalancerBuilder) Build(c *fi.CloudupModelBuilderContext) error {
if lbSpec.AccessLog != nil {
clb.AccessLog = &awstasks.ClassicLoadBalancerAccessLog{
EmitInterval: fi.PtrTo(int64(lbSpec.AccessLog.Interval)),
EmitInterval: fi.PtrTo(int32(lbSpec.AccessLog.Interval)),
Enabled: fi.PtrTo(true),
S3BucketName: lbSpec.AccessLog.Bucket,
S3BucketPrefix: lbSpec.AccessLog.BucketPrefix,

View File

@ -23,6 +23,8 @@ import (
"strings"
"sync"
elb "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing"
elbtypes "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing/types"
elbv2 "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2"
elbv2types "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2/types"
"github.com/aws/aws-sdk-go-v2/service/iam"
@ -30,7 +32,6 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go/service/route53"
"github.com/aws/smithy-go"
"k8s.io/apimachinery/pkg/util/sets"
@ -266,7 +267,7 @@ func addUntaggedRouteTables(cloud awsup.AWSCloud, clusterName string, resources
return nil
}
func matchesElbTags(tags map[string]string, actual []*elb.Tag) bool {
func matchesElbTags(tags map[string]string, actual []elbtypes.Tag) bool {
for k, v := range tags {
found := false
for _, a := range actual {
@ -1411,6 +1412,7 @@ func DeleteAutoScalingGroupLaunchTemplate(cloud fi.Cloud, r *resources.Resource)
}
func DeleteELB(cloud fi.Cloud, r *resources.Resource) error {
ctx := context.TODO()
c := cloud.(awsup.AWSCloud)
id := r.ID
@ -1419,7 +1421,7 @@ func DeleteELB(cloud fi.Cloud, r *resources.Resource) error {
request := &elb.DeleteLoadBalancerInput{
LoadBalancerName: &id,
}
_, err := c.ELB().DeleteLoadBalancer(request)
_, err := c.ELB().DeleteLoadBalancer(ctx, request)
if err != nil {
if IsDependencyViolation(err) {
return err
@ -1496,10 +1498,10 @@ func ListELBs(cloud fi.Cloud, vpcID, clusterName string) ([]*resources.Resource,
var blocks []string
for _, sg := range elb.SecurityGroups {
blocks = append(blocks, "security-group:"+aws.StringValue(sg))
blocks = append(blocks, "security-group:"+sg)
}
for _, s := range elb.Subnets {
blocks = append(blocks, "subnet:"+aws.StringValue(s))
blocks = append(blocks, "subnet:"+s)
}
blocks = append(blocks, "vpc:"+aws.StringValue(elb.VPCId))
@ -1511,7 +1513,8 @@ func ListELBs(cloud fi.Cloud, vpcID, clusterName string) ([]*resources.Resource,
return resourceTrackers, nil
}
func DescribeELBs(cloud fi.Cloud) ([]*elb.LoadBalancerDescription, map[string][]*elb.Tag, error) {
func DescribeELBs(cloud fi.Cloud) ([]elbtypes.LoadBalancerDescription, map[string][]elbtypes.Tag, error) {
ctx := context.TODO()
c := cloud.(awsup.AWSCloud)
tags := c.Tags()
@ -1519,31 +1522,33 @@ func DescribeELBs(cloud fi.Cloud) ([]*elb.LoadBalancerDescription, map[string][]
request := &elb.DescribeLoadBalancersInput{}
// ELB DescribeTags has a limit of 20 names, so we set the page size here to 20 also
request.PageSize = aws.Int64(20)
request.PageSize = aws.Int32(20)
var elbs []*elb.LoadBalancerDescription
elbTags := make(map[string][]*elb.Tag)
var elbs []elbtypes.LoadBalancerDescription
elbTags := make(map[string][]elbtypes.Tag)
var innerError error
err := c.ELB().DescribeLoadBalancersPages(request, func(p *elb.DescribeLoadBalancersOutput, lastPage bool) bool {
if len(p.LoadBalancerDescriptions) == 0 {
return true
paginator := elb.NewDescribeLoadBalancersPaginator(c.ELB(), request)
for paginator.HasMorePages() {
page, err := paginator.NextPage(ctx)
if err != nil {
return nil, nil, fmt.Errorf("error listing elbs: %v", err)
}
if len(page.LoadBalancerDescriptions) == 0 {
continue
}
tagRequest := &elb.DescribeTagsInput{}
nameToELB := make(map[string]*elb.LoadBalancerDescription)
for _, elb := range p.LoadBalancerDescriptions {
nameToELB := make(map[string]elbtypes.LoadBalancerDescription)
for _, elb := range page.LoadBalancerDescriptions {
name := aws.StringValue(elb.LoadBalancerName)
nameToELB[name] = elb
tagRequest.LoadBalancerNames = append(tagRequest.LoadBalancerNames, elb.LoadBalancerName)
tagRequest.LoadBalancerNames = append(tagRequest.LoadBalancerNames, aws.StringValue(elb.LoadBalancerName))
}
tagResponse, err := c.ELB().DescribeTags(tagRequest)
tagResponse, err := c.ELB().DescribeTags(ctx, tagRequest)
if err != nil {
innerError = fmt.Errorf("error listing elb Tags: %v", err)
return false
return nil, nil, fmt.Errorf("error listing elb Tags: %v", err)
}
for _, t := range tagResponse.TagDescriptions {
@ -1558,14 +1563,6 @@ func DescribeELBs(cloud fi.Cloud) ([]*elb.LoadBalancerDescription, map[string][]
elb := nameToELB[elbName]
elbs = append(elbs, 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 elbs, elbTags, nil
}
@ -2156,7 +2153,7 @@ func FindASGName(tags []*autoscaling.TagDescription) string {
return ""
}
func FindELBName(tags []*elb.Tag) string {
func FindELBName(tags []elbtypes.Tag) string {
if name, found := awsup.FindELBTag(tags, "Name"); found {
return name
}

View File

@ -21,10 +21,10 @@ import (
"sort"
"testing"
elbtypes "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing/types"
iamtypes "github.com/aws/aws-sdk-go-v2/service/iam/types"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/elb"
"k8s.io/kops/cloudmock/aws/mockec2"
"k8s.io/kops/cloudmock/aws/mockiam"
"k8s.io/kops/pkg/resources"
@ -345,12 +345,12 @@ func TestSharedVolume(t *testing.T) {
func TestMatchesElbTags(t *testing.T) {
tc := []struct {
tags map[string]string
actual []*elb.Tag
actual []elbtypes.Tag
expected bool
}{
{
tags: map[string]string{"tagkey1": "tagvalue1"},
actual: []*elb.Tag{
actual: []elbtypes.Tag{
{
Key: fi.PtrTo("tagkey1"),
Value: fi.PtrTo("tagvalue1"),
@ -364,7 +364,7 @@ func TestMatchesElbTags(t *testing.T) {
},
{
tags: map[string]string{"tagkey2": "tagvalue2"},
actual: []*elb.Tag{
actual: []elbtypes.Tag{
{
Key: fi.PtrTo("tagkey1"),
Value: fi.PtrTo("tagvalue1"),
@ -378,7 +378,7 @@ func TestMatchesElbTags(t *testing.T) {
},
{
tags: map[string]string{"tagkey3": "tagvalue3"},
actual: []*elb.Tag{
actual: []elbtypes.Tag{
{
Key: fi.PtrTo("tagkey1"),
Value: fi.PtrTo("tagvalue1"),

View File

@ -17,14 +17,16 @@ limitations under the License.
package awstasks
import (
"context"
"fmt"
"sort"
"strconv"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go-v2/aws"
elb "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing"
elbtypes "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing/types"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go/service/route53"
"k8s.io/klog/v2"
"k8s.io/kops/pkg/wellknownservices"
@ -86,14 +88,14 @@ func (e *ClassicLoadBalancer) CompareWithID() *string {
}
type ClassicLoadBalancerListener struct {
InstancePort int
InstancePort int32
SSLCertificateID string
}
func (e *ClassicLoadBalancerListener) mapToAWS(loadBalancerPort int64) *elb.Listener {
l := &elb.Listener{
LoadBalancerPort: aws.Int64(loadBalancerPort),
InstancePort: aws.Int64(int64(e.InstancePort)),
func (e *ClassicLoadBalancerListener) mapToAWS(loadBalancerPort int32) elbtypes.Listener {
l := elbtypes.Listener{
LoadBalancerPort: loadBalancerPort,
InstancePort: aws.Int32(e.InstancePort),
}
if e.SSLCertificateID != "" {
@ -114,18 +116,18 @@ func (e *ClassicLoadBalancerListener) GetDependencies(tasks map[string]fi.Cloudu
return nil
}
func findLoadBalancerByLoadBalancerName(cloud awsup.AWSCloud, loadBalancerName string) (*elb.LoadBalancerDescription, error) {
func findLoadBalancerByLoadBalancerName(ctx context.Context, cloud awsup.AWSCloud, loadBalancerName string) (*elbtypes.LoadBalancerDescription, error) {
request := &elb.DescribeLoadBalancersInput{
LoadBalancerNames: []*string{&loadBalancerName},
LoadBalancerNames: []string{loadBalancerName},
}
found, err := describeLoadBalancers(cloud, request, func(lb *elb.LoadBalancerDescription) bool {
found, err := describeLoadBalancers(ctx, cloud, request, func(lb elbtypes.LoadBalancerDescription) bool {
// TODO: Filter by cluster?
if aws.StringValue(lb.LoadBalancerName) == loadBalancerName {
if aws.ToString(lb.LoadBalancerName) == loadBalancerName {
return true
}
klog.Warningf("Got ELB with unexpected name: %q", aws.StringValue(lb.LoadBalancerName))
klog.Warningf("Got ELB with unexpected name: %q", aws.ToString(lb.LoadBalancerName))
return false
})
if err != nil {
@ -146,29 +148,30 @@ func findLoadBalancerByLoadBalancerName(cloud awsup.AWSCloud, loadBalancerName s
return nil, fmt.Errorf("Found multiple ELBs with name %q", loadBalancerName)
}
return found[0], nil
return &found[0], nil
}
func findLoadBalancerByAlias(cloud awsup.AWSCloud, alias *route53.AliasTarget) (*elb.LoadBalancerDescription, error) {
func findLoadBalancerByAlias(cloud awsup.AWSCloud, alias *route53.AliasTarget) (*elbtypes.LoadBalancerDescription, error) {
ctx := context.TODO()
// TODO: Any way to avoid listing all ELBs?
request := &elb.DescribeLoadBalancersInput{}
dnsName := aws.StringValue(alias.DNSName)
dnsName := aws.ToString(alias.DNSName)
matchDnsName := strings.TrimSuffix(dnsName, ".")
if matchDnsName == "" {
return nil, fmt.Errorf("DNSName not set on AliasTarget")
}
matchHostedZoneId := aws.StringValue(alias.HostedZoneId)
matchHostedZoneId := aws.ToString(alias.HostedZoneId)
found, err := describeLoadBalancers(cloud, request, func(lb *elb.LoadBalancerDescription) bool {
found, err := describeLoadBalancers(ctx, cloud, request, func(lb elbtypes.LoadBalancerDescription) bool {
// TODO: Filter by cluster?
if matchHostedZoneId != aws.StringValue(lb.CanonicalHostedZoneNameID) {
if matchHostedZoneId != aws.ToString(lb.CanonicalHostedZoneNameID) {
return false
}
lbDnsName := aws.StringValue(lb.DNSName)
lbDnsName := aws.ToString(lb.DNSName)
lbDnsName = strings.TrimSuffix(lbDnsName, ".")
return lbDnsName == matchDnsName || "dualstack."+lbDnsName == matchDnsName
})
@ -184,24 +187,24 @@ func findLoadBalancerByAlias(cloud awsup.AWSCloud, alias *route53.AliasTarget) (
return nil, fmt.Errorf("Found multiple ELBs with DNSName %q", dnsName)
}
return found[0], nil
return &found[0], nil
}
func describeLoadBalancers(cloud awsup.AWSCloud, request *elb.DescribeLoadBalancersInput, filter func(*elb.LoadBalancerDescription) bool) ([]*elb.LoadBalancerDescription, error) {
var found []*elb.LoadBalancerDescription
err := cloud.ELB().DescribeLoadBalancersPages(request, func(p *elb.DescribeLoadBalancersOutput, lastPage bool) (shouldContinue bool) {
for _, lb := range p.LoadBalancerDescriptions {
func describeLoadBalancers(ctx context.Context, cloud awsup.AWSCloud, request *elb.DescribeLoadBalancersInput, filter func(elbtypes.LoadBalancerDescription) bool) ([]elbtypes.LoadBalancerDescription, error) {
var found []elbtypes.LoadBalancerDescription
paginator := elb.NewDescribeLoadBalancersPaginator(cloud.ELB(), request)
for paginator.HasMorePages() {
output, err := paginator.NextPage(ctx)
if err != nil {
return nil, fmt.Errorf("error listing ELBs: %w", err)
}
for _, lb := range output.LoadBalancerDescriptions {
if filter(lb) {
found = append(found, lb)
}
}
return true
})
if err != nil {
return nil, fmt.Errorf("error listing ELBs: %v", err)
}
return found, nil
}
@ -214,6 +217,7 @@ func (e *ClassicLoadBalancer) getHostedZoneId() *string {
}
func (e *ClassicLoadBalancer) Find(c *fi.CloudupContext) (*ClassicLoadBalancer, error) {
ctx := c.Context()
cloud := c.T.Cloud.(awsup.AWSCloud)
lb, err := cloud.FindELBByNameTag(fi.ValueOf(e.Name))
@ -241,29 +245,29 @@ func (e *ClassicLoadBalancer) Find(c *fi.CloudupContext) (*ClassicLoadBalancer,
}
actual.Tags = make(map[string]string)
for _, tag := range tagMap[*e.LoadBalancerName] {
if strings.HasPrefix(aws.StringValue(tag.Key), "aws:cloudformation:") {
if strings.HasPrefix(aws.ToString(tag.Key), "aws:cloudformation:") {
continue
}
actual.Tags[aws.StringValue(tag.Key)] = aws.StringValue(tag.Value)
actual.Tags[aws.ToString(tag.Key)] = aws.ToString(tag.Value)
}
for _, subnet := range lb.Subnets {
actual.Subnets = append(actual.Subnets, &Subnet{ID: subnet})
actual.Subnets = append(actual.Subnets, &Subnet{ID: aws.String(subnet)})
}
for _, sg := range lb.SecurityGroups {
actual.SecurityGroups = append(actual.SecurityGroups, &SecurityGroup{ID: sg})
actual.SecurityGroups = append(actual.SecurityGroups, &SecurityGroup{ID: aws.String(sg)})
}
actual.Listeners = make(map[string]*ClassicLoadBalancerListener)
for _, ld := range lb.ListenerDescriptions {
l := ld.Listener
loadBalancerPort := strconv.FormatInt(aws.Int64Value(l.LoadBalancerPort), 10)
loadBalancerPort := strconv.FormatInt(int64(l.LoadBalancerPort), 10)
actualListener := &ClassicLoadBalancerListener{}
actualListener.InstancePort = int(aws.Int64Value(l.InstancePort))
actualListener.SSLCertificateID = aws.StringValue(l.SSLCertificateId)
actualListener.InstancePort = aws.ToInt32(l.InstancePort)
actualListener.SSLCertificateID = aws.ToString(l.SSLCertificateId)
actual.Listeners[loadBalancerPort] = actualListener
}
@ -274,20 +278,19 @@ func (e *ClassicLoadBalancer) Find(c *fi.CloudupContext) (*ClassicLoadBalancer,
actual.HealthCheck = healthcheck
// Extract attributes
lbAttributes, err := findELBAttributes(cloud, aws.StringValue(lb.LoadBalancerName))
lbAttributes, err := findELBAttributes(ctx, cloud, aws.ToString(lb.LoadBalancerName))
if err != nil {
return nil, err
}
klog.V(4).Infof("ELB attributes: %+v", lbAttributes)
if lbAttributes != nil {
actual.AccessLog = &ClassicLoadBalancerAccessLog{}
actual.AccessLog = &ClassicLoadBalancerAccessLog{
Enabled: aws.Bool(lbAttributes.AccessLog.Enabled),
}
if lbAttributes.AccessLog.EmitInterval != nil {
actual.AccessLog.EmitInterval = lbAttributes.AccessLog.EmitInterval
}
if lbAttributes.AccessLog.Enabled != nil {
actual.AccessLog.Enabled = lbAttributes.AccessLog.Enabled
}
if lbAttributes.AccessLog.S3BucketName != nil {
actual.AccessLog.S3BucketName = lbAttributes.AccessLog.S3BucketName
}
@ -296,8 +299,8 @@ func (e *ClassicLoadBalancer) Find(c *fi.CloudupContext) (*ClassicLoadBalancer,
}
actual.ConnectionDraining = &ClassicLoadBalancerConnectionDraining{}
if lbAttributes.ConnectionDraining.Enabled != nil {
actual.ConnectionDraining.Enabled = lbAttributes.ConnectionDraining.Enabled
if lbAttributes.ConnectionDraining.Enabled {
actual.ConnectionDraining.Enabled = aws.Bool(lbAttributes.ConnectionDraining.Enabled)
}
if lbAttributes.ConnectionDraining.Timeout != nil {
actual.ConnectionDraining.Timeout = lbAttributes.ConnectionDraining.Timeout
@ -308,9 +311,8 @@ func (e *ClassicLoadBalancer) Find(c *fi.CloudupContext) (*ClassicLoadBalancer,
actual.ConnectionSettings.IdleTimeout = lbAttributes.ConnectionSettings.IdleTimeout
}
actual.CrossZoneLoadBalancing = &ClassicLoadBalancerCrossZoneLoadBalancing{}
if lbAttributes.CrossZoneLoadBalancing.Enabled != nil {
actual.CrossZoneLoadBalancing.Enabled = lbAttributes.CrossZoneLoadBalancing.Enabled
actual.CrossZoneLoadBalancing = &ClassicLoadBalancerCrossZoneLoadBalancing{
Enabled: aws.Bool(lbAttributes.CrossZoneLoadBalancing.Enabled),
}
}
@ -332,7 +334,7 @@ func (e *ClassicLoadBalancer) Find(c *fi.CloudupContext) (*ClassicLoadBalancer,
// 1. We don't want to force a rename of the ELB, because that is a destructive operation
// 2. We were creating ELBs with insufficiently qualified names previously
if fi.ValueOf(e.LoadBalancerName) != fi.ValueOf(actual.LoadBalancerName) {
klog.V(2).Infof("Reusing existing load balancer with name: %q", aws.StringValue(actual.LoadBalancerName))
klog.V(2).Infof("Reusing existing load balancer with name: %q", aws.ToString(actual.LoadBalancerName))
e.LoadBalancerName = actual.LoadBalancerName
}
@ -434,6 +436,7 @@ func (_ *ClassicLoadBalancer) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Cl
if shared {
return nil
}
ctx := context.TODO()
var loadBalancerName string
if a == nil {
@ -447,27 +450,27 @@ func (_ *ClassicLoadBalancer) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Cl
request.Scheme = e.Scheme
for _, subnet := range e.Subnets {
request.Subnets = append(request.Subnets, subnet.ID)
request.Subnets = append(request.Subnets, aws.ToString(subnet.ID))
}
for _, sg := range e.SecurityGroups {
request.SecurityGroups = append(request.SecurityGroups, sg.ID)
request.SecurityGroups = append(request.SecurityGroups, aws.ToString(sg.ID))
}
request.Listeners = []*elb.Listener{}
request.Listeners = []elbtypes.Listener{}
for loadBalancerPort, listener := range e.Listeners {
loadBalancerPortInt, err := strconv.ParseInt(loadBalancerPort, 10, 64)
loadBalancerPortInt, err := strconv.ParseInt(loadBalancerPort, 10, 32)
if err != nil {
return fmt.Errorf("error parsing load balancer listener port: %q", loadBalancerPort)
}
awsListener := listener.mapToAWS(loadBalancerPortInt)
awsListener := listener.mapToAWS(int32(loadBalancerPortInt))
request.Listeners = append(request.Listeners, awsListener)
}
klog.V(2).Infof("Creating ELB with Name:%q", loadBalancerName)
response, err := t.Cloud.ELB().CreateLoadBalancer(request)
response, err := t.Cloud.ELB().CreateLoadBalancer(ctx, request)
if err != nil {
return fmt.Errorf("error creating ELB: %v", err)
}
@ -475,7 +478,7 @@ func (_ *ClassicLoadBalancer) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Cl
e.DNSName = response.DNSName
// Requery to get the CanonicalHostedZoneNameID
lb, err := findLoadBalancerByLoadBalancerName(t.Cloud, loadBalancerName)
lb, err := findLoadBalancerByLoadBalancerName(ctx, t.Cloud, loadBalancerName)
if err != nil {
return err
}
@ -501,11 +504,11 @@ func (_ *ClassicLoadBalancer) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Cl
oldSubnetIDs := slice.GetUniqueStrings(expectedSubnets, actualSubnets)
if len(oldSubnetIDs) > 0 {
request := &elb.DetachLoadBalancerFromSubnetsInput{}
request.SetLoadBalancerName(loadBalancerName)
request.SetSubnets(aws.StringSlice(oldSubnetIDs))
request.LoadBalancerName = aws.String(loadBalancerName)
request.Subnets = oldSubnetIDs
klog.V(2).Infof("Detaching Load Balancer from old subnets")
if _, err := t.Cloud.ELB().DetachLoadBalancerFromSubnets(request); err != nil {
if _, err := t.Cloud.ELB().DetachLoadBalancerFromSubnets(ctx, request); err != nil {
return fmt.Errorf("Error detaching Load Balancer from old subnets: %v", err)
}
}
@ -513,11 +516,11 @@ func (_ *ClassicLoadBalancer) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Cl
newSubnetIDs := slice.GetUniqueStrings(actualSubnets, expectedSubnets)
if len(newSubnetIDs) > 0 {
request := &elb.AttachLoadBalancerToSubnetsInput{}
request.SetLoadBalancerName(loadBalancerName)
request.SetSubnets(aws.StringSlice(newSubnetIDs))
request.LoadBalancerName = aws.String(loadBalancerName)
request.Subnets = newSubnetIDs
klog.V(2).Infof("Attaching Load Balancer to new subnets")
if _, err := t.Cloud.ELB().AttachLoadBalancerToSubnets(request); err != nil {
if _, err := t.Cloud.ELB().AttachLoadBalancerToSubnets(ctx, request); err != nil {
return fmt.Errorf("Error attaching Load Balancer to new subnets: %v", err)
}
}
@ -527,27 +530,27 @@ func (_ *ClassicLoadBalancer) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Cl
request := &elb.ApplySecurityGroupsToLoadBalancerInput{}
request.LoadBalancerName = aws.String(loadBalancerName)
for _, sg := range e.SecurityGroups {
request.SecurityGroups = append(request.SecurityGroups, sg.ID)
request.SecurityGroups = append(request.SecurityGroups, aws.ToString(sg.ID))
}
klog.V(2).Infof("Updating Load Balancer Security Groups")
if _, err := t.Cloud.ELB().ApplySecurityGroupsToLoadBalancer(request); err != nil {
if _, err := t.Cloud.ELB().ApplySecurityGroupsToLoadBalancer(ctx, request); err != nil {
return fmt.Errorf("Error updating security groups on Load Balancer: %v", err)
}
}
if changes.Listeners != nil {
elbDescription, err := findLoadBalancerByLoadBalancerName(t.Cloud, loadBalancerName)
elbDescription, err := findLoadBalancerByLoadBalancerName(ctx, t.Cloud, loadBalancerName)
if err != nil {
return fmt.Errorf("error getting load balancer by name: %v", err)
}
if elbDescription != nil {
// deleting the listener before recreating it
t.Cloud.ELB().DeleteLoadBalancerListeners(&elb.DeleteLoadBalancerListenersInput{
t.Cloud.ELB().DeleteLoadBalancerListeners(ctx, &elb.DeleteLoadBalancerListenersInput{
LoadBalancerName: aws.String(loadBalancerName),
LoadBalancerPorts: []*int64{aws.Int64(443)},
LoadBalancerPorts: []int32{443},
})
}
@ -555,17 +558,17 @@ func (_ *ClassicLoadBalancer) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Cl
request.LoadBalancerName = aws.String(loadBalancerName)
for loadBalancerPort, listener := range changes.Listeners {
loadBalancerPortInt, err := strconv.ParseInt(loadBalancerPort, 10, 64)
loadBalancerPortInt, err := strconv.ParseInt(loadBalancerPort, 10, 32)
if err != nil {
return fmt.Errorf("error parsing load balancer listener port: %q", loadBalancerPort)
}
awsListener := listener.mapToAWS(loadBalancerPortInt)
awsListener := listener.mapToAWS(int32(loadBalancerPortInt))
request.Listeners = append(request.Listeners, awsListener)
}
klog.V(2).Infof("Creating LoadBalancer listeners")
_, err = t.Cloud.ELB().CreateLoadBalancerListeners(request)
_, err = t.Cloud.ELB().CreateLoadBalancerListeners(ctx, request)
if err != nil {
return fmt.Errorf("error creating LoadBalancerListeners: %v", err)
}
@ -583,7 +586,7 @@ func (_ *ClassicLoadBalancer) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Cl
if changes.HealthCheck != nil && e.HealthCheck != nil {
request := &elb.ConfigureHealthCheckInput{}
request.LoadBalancerName = aws.String(loadBalancerName)
request.HealthCheck = &elb.HealthCheck{
request.HealthCheck = &elbtypes.HealthCheck{
Target: e.HealthCheck.Target,
HealthyThreshold: e.HealthCheck.HealthyThreshold,
UnhealthyThreshold: e.HealthCheck.UnhealthyThreshold,
@ -593,7 +596,7 @@ func (_ *ClassicLoadBalancer) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Cl
klog.V(2).Infof("Configuring health checks on ELB %q", loadBalancerName)
_, err := t.Cloud.ELB().ConfigureHealthCheck(request)
_, err := t.Cloud.ELB().ConfigureHealthCheck(ctx, request)
if err != nil {
return fmt.Errorf("error configuring health checks on ELB: %v", err)
}
@ -627,29 +630,29 @@ type terraformLoadBalancer struct {
AccessLog *terraformLoadBalancerAccessLog `cty:"access_logs"`
ConnectionDraining *bool `cty:"connection_draining"`
ConnectionDrainingTimeout *int64 `cty:"connection_draining_timeout"`
ConnectionDrainingTimeout *int32 `cty:"connection_draining_timeout"`
CrossZoneLoadBalancing *bool `cty:"cross_zone_load_balancing"`
IdleTimeout *int64 `cty:"idle_timeout"`
IdleTimeout *int32 `cty:"idle_timeout"`
Tags map[string]string `cty:"tags"`
}
type terraformLoadBalancerListener struct {
InstancePort int `cty:"instance_port"`
InstancePort int32 `cty:"instance_port"`
InstanceProtocol string `cty:"instance_protocol"`
LBPort int64 `cty:"lb_port"`
LBPort int32 `cty:"lb_port"`
LBProtocol string `cty:"lb_protocol"`
SSLCertificateID *string `cty:"ssl_certificate_id"`
}
type terraformLoadBalancerHealthCheck struct {
Target *string `cty:"target"`
HealthyThreshold *int64 `cty:"healthy_threshold"`
UnhealthyThreshold *int64 `cty:"unhealthy_threshold"`
Interval *int64 `cty:"interval"`
Timeout *int64 `cty:"timeout"`
HealthyThreshold *int32 `cty:"healthy_threshold"`
UnhealthyThreshold *int32 `cty:"unhealthy_threshold"`
Interval *int32 `cty:"interval"`
Timeout *int32 `cty:"timeout"`
}
func (_ *ClassicLoadBalancer) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *ClassicLoadBalancer) error {
@ -691,7 +694,7 @@ func (_ *ClassicLoadBalancer) RenderTerraform(t *terraform.TerraformTarget, a, e
tf.Listener = append(tf.Listener, &terraformLoadBalancerListener{
InstanceProtocol: "SSL",
InstancePort: listener.InstancePort,
LBPort: loadBalancerPortInt,
LBPort: int32(loadBalancerPortInt),
LBProtocol: "SSL",
SSLCertificateID: &listener.SSLCertificateID,
})
@ -699,7 +702,7 @@ func (_ *ClassicLoadBalancer) RenderTerraform(t *terraform.TerraformTarget, a, e
tf.Listener = append(tf.Listener, &terraformLoadBalancerListener{
InstanceProtocol: "TCP",
InstancePort: listener.InstancePort,
LBPort: loadBalancerPortInt,
LBPort: int32(loadBalancerPortInt),
LBProtocol: "TCP",
})
}

View File

@ -17,17 +17,19 @@ limitations under the License.
package awstasks
import (
"context"
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go-v2/aws"
elb "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing"
elbtypes "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing/types"
"k8s.io/klog/v2"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/awsup"
)
type ClassicLoadBalancerAccessLog struct {
EmitInterval *int64
EmitInterval *int32
Enabled *bool
S3BucketName *string
S3BucketPrefix *string
@ -38,7 +40,7 @@ func (_ *ClassicLoadBalancerAccessLog) GetDependencies(tasks map[string]fi.Cloud
}
type terraformLoadBalancerAccessLog struct {
EmitInterval *int64 `cty:"interval"`
EmitInterval *int32 `cty:"interval"`
Enabled *bool `cty:"enabled"`
S3BucketName *string `cty:"bucket"`
S3BucketPrefix *string `cty:"bucket_prefix"`
@ -55,7 +57,7 @@ type terraformLoadBalancerAccessLog struct {
type ClassicLoadBalancerConnectionDraining struct {
Enabled *bool
Timeout *int64
Timeout *int32
}
func (_ *ClassicLoadBalancerConnectionDraining) GetDependencies(tasks map[string]fi.CloudupTask) []fi.CloudupTask {
@ -71,19 +73,19 @@ func (_ *ClassicLoadBalancerCrossZoneLoadBalancing) GetDependencies(tasks map[st
}
type ClassicLoadBalancerConnectionSettings struct {
IdleTimeout *int64
IdleTimeout *int32
}
func (_ *ClassicLoadBalancerConnectionSettings) GetDependencies(tasks map[string]fi.CloudupTask) []fi.CloudupTask {
return nil
}
func findELBAttributes(cloud awsup.AWSCloud, name string) (*elb.LoadBalancerAttributes, error) {
func findELBAttributes(ctx context.Context, cloud awsup.AWSCloud, name string) (*elbtypes.LoadBalancerAttributes, error) {
request := &elb.DescribeLoadBalancerAttributesInput{
LoadBalancerName: aws.String(name),
}
response, err := cloud.ELB().DescribeLoadBalancerAttributes(request)
response, err := cloud.ELB().DescribeLoadBalancerAttributes(ctx, request)
if err != nil {
return nil, err
}
@ -102,34 +104,35 @@ func (_ *ClassicLoadBalancer) modifyLoadBalancerAttributes(t *awsup.AWSAPITarget
klog.V(4).Infof("No LoadBalancerAttribute changes; skipping update")
return nil
}
ctx := context.TODO()
loadBalancerName := fi.ValueOf(e.LoadBalancerName)
request := &elb.ModifyLoadBalancerAttributesInput{}
request.LoadBalancerName = e.LoadBalancerName
request.LoadBalancerAttributes = &elb.LoadBalancerAttributes{}
request.LoadBalancerAttributes = &elbtypes.LoadBalancerAttributes{}
// Setting mandatory attributes to default values if empty
request.LoadBalancerAttributes.AccessLog = &elb.AccessLog{}
request.LoadBalancerAttributes.AccessLog = &elbtypes.AccessLog{}
if e.AccessLog == nil || e.AccessLog.Enabled == nil {
request.LoadBalancerAttributes.AccessLog.Enabled = fi.PtrTo(false)
request.LoadBalancerAttributes.AccessLog.Enabled = false
}
request.LoadBalancerAttributes.ConnectionDraining = &elb.ConnectionDraining{}
request.LoadBalancerAttributes.ConnectionDraining = &elbtypes.ConnectionDraining{}
if e.ConnectionDraining == nil || e.ConnectionDraining.Enabled == nil {
request.LoadBalancerAttributes.ConnectionDraining.Enabled = fi.PtrTo(false)
request.LoadBalancerAttributes.ConnectionDraining.Enabled = false
}
if e.ConnectionDraining == nil || e.ConnectionDraining.Timeout == nil {
request.LoadBalancerAttributes.ConnectionDraining.Timeout = fi.PtrTo(int64(300))
request.LoadBalancerAttributes.ConnectionDraining.Timeout = aws.Int32(300)
}
request.LoadBalancerAttributes.ConnectionSettings = &elb.ConnectionSettings{}
request.LoadBalancerAttributes.ConnectionSettings = &elbtypes.ConnectionSettings{}
if e.ConnectionSettings == nil || e.ConnectionSettings.IdleTimeout == nil {
request.LoadBalancerAttributes.ConnectionSettings.IdleTimeout = fi.PtrTo(int64(60))
request.LoadBalancerAttributes.ConnectionSettings.IdleTimeout = aws.Int32(60)
}
request.LoadBalancerAttributes.CrossZoneLoadBalancing = &elb.CrossZoneLoadBalancing{}
request.LoadBalancerAttributes.CrossZoneLoadBalancing = &elbtypes.CrossZoneLoadBalancing{}
if e.CrossZoneLoadBalancing == nil || e.CrossZoneLoadBalancing.Enabled == nil {
request.LoadBalancerAttributes.CrossZoneLoadBalancing.Enabled = fi.PtrTo(false)
request.LoadBalancerAttributes.CrossZoneLoadBalancing.Enabled = false
} else {
request.LoadBalancerAttributes.CrossZoneLoadBalancing.Enabled = e.CrossZoneLoadBalancing.Enabled
request.LoadBalancerAttributes.CrossZoneLoadBalancing.Enabled = aws.ToBool(e.CrossZoneLoadBalancing.Enabled)
}
// Setting non mandatory values only if not empty
@ -147,7 +150,7 @@ func (_ *ClassicLoadBalancer) modifyLoadBalancerAttributes(t *awsup.AWSAPITarget
//}
if e.AccessLog != nil && e.AccessLog.Enabled != nil {
request.LoadBalancerAttributes.AccessLog.Enabled = e.AccessLog.Enabled
request.LoadBalancerAttributes.AccessLog.Enabled = aws.ToBool(e.AccessLog.Enabled)
}
if e.AccessLog != nil && e.AccessLog.EmitInterval != nil {
request.LoadBalancerAttributes.AccessLog.EmitInterval = e.AccessLog.EmitInterval
@ -159,7 +162,7 @@ func (_ *ClassicLoadBalancer) modifyLoadBalancerAttributes(t *awsup.AWSAPITarget
request.LoadBalancerAttributes.AccessLog.S3BucketPrefix = e.AccessLog.S3BucketPrefix
}
if e.ConnectionDraining != nil && e.ConnectionDraining.Enabled != nil {
request.LoadBalancerAttributes.ConnectionDraining.Enabled = e.ConnectionDraining.Enabled
request.LoadBalancerAttributes.ConnectionDraining.Enabled = aws.ToBool(e.ConnectionDraining.Enabled)
}
if e.ConnectionDraining != nil && e.ConnectionDraining.Timeout != nil {
request.LoadBalancerAttributes.ConnectionDraining.Timeout = e.ConnectionDraining.Timeout
@ -170,7 +173,7 @@ func (_ *ClassicLoadBalancer) modifyLoadBalancerAttributes(t *awsup.AWSAPITarget
klog.V(2).Infof("Configuring ELB attributes for ELB %q", loadBalancerName)
response, err := t.Cloud.ELB().ModifyLoadBalancerAttributes(request)
response, err := t.Cloud.ELB().ModifyLoadBalancerAttributes(ctx, request)
if err != nil {
return fmt.Errorf("error configuring ELB attributes for ELB %q: %v", loadBalancerName, err)
}

View File

@ -17,18 +17,18 @@ limitations under the License.
package awstasks
import (
"github.com/aws/aws-sdk-go/service/elb"
elbtypes "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing/types"
"k8s.io/kops/upup/pkg/fi"
)
type ClassicLoadBalancerHealthCheck struct {
Target *string
HealthyThreshold *int64
UnhealthyThreshold *int64
HealthyThreshold *int32
UnhealthyThreshold *int32
Interval *int64
Timeout *int64
Interval *int32
Timeout *int32
}
var _ fi.CloudupHasDependencies = &ClassicLoadBalancerListener{}
@ -37,7 +37,7 @@ func (e *ClassicLoadBalancerHealthCheck) GetDependencies(tasks map[string]fi.Clo
return nil
}
func findHealthCheck(lb *elb.LoadBalancerDescription) (*ClassicLoadBalancerHealthCheck, error) {
func findHealthCheck(lb *elbtypes.LoadBalancerDescription) (*ClassicLoadBalancerHealthCheck, error) {
if lb == nil || lb.HealthCheck == nil {
return nil, nil
}

View File

@ -25,9 +25,9 @@ import (
"time"
"github.com/aws/aws-sdk-go-v2/aws"
elb "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing"
elbv2 "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2"
elbv2types "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2/types"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go/service/route53"
"k8s.io/klog/v2"
"k8s.io/kops/pkg/truncate"
@ -740,12 +740,13 @@ func (d deleteClassicLoadBalancer) DeferDeletion() bool {
}
func (d deleteClassicLoadBalancer) Delete(t fi.CloudupTarget) error {
ctx := context.TODO()
awsTarget, ok := t.(*awsup.AWSAPITarget)
if !ok {
return fmt.Errorf("unexpected target type for deletion: %T", t)
}
_, err := awsTarget.Cloud.ELB().DeleteLoadBalancer(&elb.DeleteLoadBalancerInput{
_, err := awsTarget.Cloud.ELB().DeleteLoadBalancer(ctx, &elb.DeleteLoadBalancerInput{
LoadBalancerName: d.LoadBalancerName,
})
if err != nil {

View File

@ -34,6 +34,8 @@ import (
"github.com/aws/aws-sdk-go-v2/aws/arn"
"github.com/aws/aws-sdk-go-v2/aws/retry"
elb "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing"
elbtypes "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing/types"
elbv2 "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2"
elbv2types "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2/types"
"github.com/aws/aws-sdk-go-v2/service/iam"
@ -46,8 +48,6 @@ import (
"github.com/aws/aws-sdk-go/service/autoscaling/autoscalingiface"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go/service/elb/elbiface"
"github.com/aws/aws-sdk-go/service/route53"
"github.com/aws/aws-sdk-go/service/route53/route53iface"
"github.com/aws/aws-sdk-go/service/sts"
@ -128,7 +128,7 @@ type AWSCloud interface {
Session() (*session.Session, error)
EC2() ec2iface.EC2API
IAM() awsinterfaces.IAMAPI
ELB() elbiface.ELBAPI
ELB() awsinterfaces.ELBAPI
ELBV2() awsinterfaces.ELBV2API
Autoscaling() autoscalingiface.AutoScalingAPI
Route53() route53iface.Route53API
@ -161,8 +161,8 @@ type AWSCloud interface {
// RemoveELBTags will remove tags from the specified loadBalancer, retrying up to MaxCreateTagsAttempts times if it hits an eventual-consistency type error
RemoveELBTags(loadBalancerName string, tags map[string]string) error
RemoveELBV2Tags(ResourceArn string, tags map[string]string) error
FindELBByNameTag(findNameTag string) (*elb.LoadBalancerDescription, error)
DescribeELBTags(loadBalancerNames []string) (map[string][]*elb.Tag, error)
FindELBByNameTag(findNameTag string) (*elbtypes.LoadBalancerDescription, error)
DescribeELBTags(loadBalancerNames []string) (map[string][]elbtypes.Tag, error)
// TODO: Remove, replace with awsup.ListELBV2LoadBalancers
DescribeELBV2Tags(loadBalancerNames []string) (map[string][]elbv2types.Tag, error)
FindELBV2NetworkInterfacesByName(vpcID string, loadBalancerName string) ([]*ec2.NetworkInterface, error)
@ -197,7 +197,7 @@ type AWSCloud interface {
type awsCloudImplementation struct {
ec2 *ec2.EC2
iam *iam.Client
elb *elb.ELB
elb *elb.Client
elbv2 *elbv2.Client
autoscaling *autoscaling.AutoScaling
route53 *route53.Route53
@ -333,18 +333,7 @@ func NewAWSCloud(region string, tags map[string]string) (AWSCloud, error) {
c.addHandlers(region, &c.ec2.Handlers)
c.iam = iam.NewFromConfig(cfgV2)
sess, err = session.NewSessionWithOptions(session.Options{
Config: *config,
SharedConfigState: session.SharedConfigEnable,
})
if err != nil {
return c, err
}
c.elb = elb.New(sess, config)
c.elb.Handlers.Send.PushFront(requestLogger)
c.addHandlers(region, &c.elb.Handlers)
c.elb = elb.NewFromConfig(cfgV2)
c.elbv2 = elbv2.NewFromConfig(cfgV2)
sess, err = session.NewSessionWithOptions(session.Options{
@ -635,7 +624,7 @@ func deregisterInstance(ctx context.Context, c AWSCloud, i *cloudinstances.Cloud
if len(loadBalancerNames) != 0 {
eg.Go(func() error {
return deregisterInstanceFromClassicLoadBalancer(c, loadBalancerNames, i.ID)
return deregisterInstanceFromClassicLoadBalancer(ctx, c, loadBalancerNames, i.ID)
})
}
@ -653,15 +642,15 @@ func deregisterInstance(ctx context.Context, c AWSCloud, i *cloudinstances.Cloud
}
// deregisterInstanceFromClassicLoadBalancer ensures that connectionDraining completes for the associated classic loadBalancer to ensure no dropped connections.
func deregisterInstanceFromClassicLoadBalancer(c AWSCloud, loadBalancerNames []string, instanceId string) error {
func deregisterInstanceFromClassicLoadBalancer(ctx context.Context, c AWSCloud, loadBalancerNames []string, instanceId string) error {
klog.Infof("Deregistering instance from classic loadBalancers: %v", loadBalancerNames)
for {
instanceDraining := false
for _, loadBalancerName := range loadBalancerNames {
response, err := c.ELB().DescribeInstanceHealth(&elb.DescribeInstanceHealthInput{
response, err := c.ELB().DescribeInstanceHealth(ctx, &elb.DescribeInstanceHealthInput{
LoadBalancerName: aws.String(loadBalancerName),
Instances: []*elb.Instance{{
Instances: []elbtypes.Instance{{
InstanceId: aws.String(instanceId),
}},
})
@ -676,9 +665,9 @@ func deregisterInstanceFromClassicLoadBalancer(c AWSCloud, loadBalancerNames []s
// there will be only one instance in the DescribeInstanceHealth response.
if aws.StringValue(response.InstanceStates[0].State) == instanceInServiceState {
c.ELB().DeregisterInstancesFromLoadBalancer(&elb.DeregisterInstancesFromLoadBalancerInput{
c.ELB().DeregisterInstancesFromLoadBalancer(ctx, &elb.DeregisterInstancesFromLoadBalancerInput{
LoadBalancerName: aws.String(loadBalancerName),
Instances: []*elb.Instance{{
Instances: []elbtypes.Instance{{
InstanceId: aws.String(instanceId),
}},
})
@ -1577,12 +1566,13 @@ func (c *awsCloudImplementation) GetELBTags(loadBalancerName string) (map[string
}
func getELBTags(c AWSCloud, loadBalancerName string) (map[string]string, error) {
ctx := context.TODO()
tags := map[string]string{}
request := &elb.DescribeTagsInput{
LoadBalancerNames: []*string{&loadBalancerName},
LoadBalancerNames: []string{loadBalancerName},
}
response, err := c.ELB().DescribeTags(request)
response, err := c.ELB().DescribeTags(ctx, request)
if err != nil {
return nil, fmt.Errorf("error listing tags on %v: %v", loadBalancerName, err)
}
@ -1605,18 +1595,19 @@ func createELBTags(c AWSCloud, loadBalancerName string, tags map[string]string)
if len(tags) == 0 {
return nil
}
ctx := context.TODO()
elbTags := []*elb.Tag{}
elbTags := []elbtypes.Tag{}
for k, v := range tags {
elbTags = append(elbTags, &elb.Tag{Key: aws.String(k), Value: aws.String(v)})
elbTags = append(elbTags, elbtypes.Tag{Key: aws.String(k), Value: aws.String(v)})
}
request := &elb.AddTagsInput{
Tags: elbTags,
LoadBalancerNames: []*string{&loadBalancerName},
LoadBalancerNames: []string{loadBalancerName},
}
_, err := c.ELB().AddTags(request)
_, err := c.ELB().AddTags(ctx, request)
if err != nil {
return fmt.Errorf("error creating tags on %v: %v", loadBalancerName, err)
}
@ -1633,18 +1624,19 @@ func removeELBTags(c AWSCloud, loadBalancerName string, tags map[string]string)
if len(tags) == 0 {
return nil
}
ctx := context.TODO()
elbTagKeysOnly := []*elb.TagKeyOnly{}
elbTagKeysOnly := []elbtypes.TagKeyOnly{}
for k := range tags {
elbTagKeysOnly = append(elbTagKeysOnly, &elb.TagKeyOnly{Key: aws.String(k)})
elbTagKeysOnly = append(elbTagKeysOnly, elbtypes.TagKeyOnly{Key: aws.String(k)})
}
request := &elb.RemoveTagsInput{
Tags: elbTagKeysOnly,
LoadBalancerNames: []*string{&loadBalancerName},
LoadBalancerNames: []string{loadBalancerName},
}
_, err := c.ELB().RemoveTags(request)
_, err := c.ELB().RemoveTags(ctx, request)
if err != nil {
return fmt.Errorf("error creating tags on %v: %v", loadBalancerName, err)
}
@ -1758,31 +1750,36 @@ func (c *awsCloudImplementation) AddTags(name *string, tags map[string]string) {
}
}
func (c *awsCloudImplementation) FindELBByNameTag(findNameTag string) (*elb.LoadBalancerDescription, error) {
func (c *awsCloudImplementation) FindELBByNameTag(findNameTag string) (*elbtypes.LoadBalancerDescription, error) {
return findELBByNameTag(c, findNameTag)
}
func findELBByNameTag(c AWSCloud, findNameTag string) (*elb.LoadBalancerDescription, error) {
func findELBByNameTag(c AWSCloud, findNameTag string) (*elbtypes.LoadBalancerDescription, error) {
ctx := context.TODO()
// TODO: Any way around this?
klog.V(2).Infof("Listing all ELBs for findLoadBalancerByNameTag")
request := &elb.DescribeLoadBalancersInput{}
// ELB DescribeTags has a limit of 20 names, so we set the page size here to 20 also
request.PageSize = aws.Int64(20)
request.PageSize = aws.Int32(20)
var found []*elb.LoadBalancerDescription
var found []elbtypes.LoadBalancerDescription
var innerError error
err := c.ELB().DescribeLoadBalancersPages(request, func(p *elb.DescribeLoadBalancersOutput, lastPage bool) bool {
if len(p.LoadBalancerDescriptions) == 0 {
return true
paginator := elb.NewDescribeLoadBalancersPaginator(c.ELB(), request)
for paginator.HasMorePages() {
page, err := paginator.NextPage(ctx)
if err != nil {
return nil, fmt.Errorf("error describing LoadBalancers: %w", err)
}
if len(page.LoadBalancerDescriptions) == 0 {
continue
}
// TODO: Filter by cluster?
var names []string
nameToELB := make(map[string]*elb.LoadBalancerDescription)
for _, elb := range p.LoadBalancerDescriptions {
nameToELB := make(map[string]elbtypes.LoadBalancerDescription)
for _, elb := range page.LoadBalancerDescriptions {
name := aws.StringValue(elb.LoadBalancerName)
nameToELB[name] = elb
names = append(names, name)
@ -1790,8 +1787,7 @@ func findELBByNameTag(c AWSCloud, findNameTag string) (*elb.LoadBalancerDescript
tagMap, err := c.DescribeELBTags(names)
if err != nil {
innerError = err
return false
return nil, fmt.Errorf("error describing LoadBalancer tags: %w", err)
}
for loadBalancerName, tags := range tagMap {
@ -1803,13 +1799,6 @@ func findELBByNameTag(c AWSCloud, findNameTag string) (*elb.LoadBalancerDescript
elb := nameToELB[loadBalancerName]
found = append(found, elb)
}
return true
})
if err != nil {
return nil, fmt.Errorf("error describing LoadBalancers: %v", err)
}
if innerError != nil {
return nil, fmt.Errorf("error describing LoadBalancers: %v", innerError)
}
if len(found) == 0 {
@ -1820,27 +1809,28 @@ func findELBByNameTag(c AWSCloud, findNameTag string) (*elb.LoadBalancerDescript
return nil, fmt.Errorf("Found multiple ELBs with Name %q", findNameTag)
}
return found[0], nil
return &found[0], nil
}
func (c *awsCloudImplementation) DescribeELBTags(loadBalancerNames []string) (map[string][]*elb.Tag, error) {
func (c *awsCloudImplementation) DescribeELBTags(loadBalancerNames []string) (map[string][]elbtypes.Tag, error) {
return describeELBTags(c, loadBalancerNames)
}
func describeELBTags(c AWSCloud, loadBalancerNames []string) (map[string][]*elb.Tag, error) {
func describeELBTags(c AWSCloud, loadBalancerNames []string) (map[string][]elbtypes.Tag, error) {
ctx := context.TODO()
// TODO: Filter by cluster?
request := &elb.DescribeTagsInput{}
request.LoadBalancerNames = aws.StringSlice(loadBalancerNames)
request.LoadBalancerNames = loadBalancerNames
// TODO: Cache?
klog.V(2).Infof("Querying ELB tags for %s", loadBalancerNames)
response, err := c.ELB().DescribeTags(request)
response, err := c.ELB().DescribeTags(ctx, request)
if err != nil {
return nil, err
}
tagMap := make(map[string][]*elb.Tag)
tagMap := make(map[string][]elbtypes.Tag)
for _, tagset := range response.TagDescriptions {
tagMap[aws.StringValue(tagset.LoadBalancerName)] = tagset.Tags
}
@ -2175,7 +2165,7 @@ func (c *awsCloudImplementation) IAM() awsinterfaces.IAMAPI {
return c.iam
}
func (c *awsCloudImplementation) ELB() elbiface.ELBAPI {
func (c *awsCloudImplementation) ELB() awsinterfaces.ELBAPI {
return c.elb
}

View File

@ -28,12 +28,12 @@ import (
awsconfig "github.com/aws/aws-sdk-go-v2/config"
ec2v2 "github.com/aws/aws-sdk-go-v2/service/ec2"
ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types"
elbtypes "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing/types"
elbv2types "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2/types"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/elb"
"k8s.io/klog/v2"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/truncate"
@ -133,7 +133,7 @@ func FindASGTag(tags []*autoscaling.TagDescription, key string) (string, bool) {
}
// FindELBTag find the value of the tag with the specified key
func FindELBTag(tags []*elb.Tag, key string) (string, bool) {
func FindELBTag(tags []elbtypes.Tag, key string) (string, bool) {
for _, tag := range tags {
if key == aws.StringValue(tag.Key) {
return aws.StringValue(tag.Value), true

View File

@ -21,14 +21,13 @@ import (
"fmt"
ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types"
elbtypes "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing/types"
elbv2types "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2/types"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/autoscaling/autoscalingiface"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go/service/elb/elbiface"
"github.com/aws/aws-sdk-go/service/route53/route53iface"
v1 "k8s.io/api/core/v1"
"k8s.io/klog/v2"
@ -79,7 +78,7 @@ type MockCloud struct {
MockEC2 ec2iface.EC2API
MockIAM awsinterfaces.IAMAPI
MockRoute53 route53iface.Route53API
MockELB elbiface.ELBAPI
MockELB awsinterfaces.ELBAPI
MockELBV2 awsinterfaces.ELBV2API
MockSpotinst spotinst.Cloud
MockSQS awsinterfaces.SQSAPI
@ -200,11 +199,11 @@ func (c *MockAWSCloud) RemoveELBV2Tags(ResourceArn string, tags map[string]strin
return removeELBV2Tags(c, ResourceArn, tags)
}
func (c *MockAWSCloud) FindELBByNameTag(findNameTag string) (*elb.LoadBalancerDescription, error) {
func (c *MockAWSCloud) FindELBByNameTag(findNameTag string) (*elbtypes.LoadBalancerDescription, error) {
return findELBByNameTag(c, findNameTag)
}
func (c *MockAWSCloud) DescribeELBTags(loadBalancerNames []string) (map[string][]*elb.Tag, error) {
func (c *MockAWSCloud) DescribeELBTags(loadBalancerNames []string) (map[string][]elbtypes.Tag, error) {
return describeELBTags(c, loadBalancerNames)
}
@ -249,7 +248,7 @@ func (c *MockAWSCloud) IAM() awsinterfaces.IAMAPI {
return c.MockIAM
}
func (c *MockAWSCloud) ELB() elbiface.ELBAPI {
func (c *MockAWSCloud) ELB() awsinterfaces.ELBAPI {
if c.MockELB == nil {
klog.Fatalf("MockAWSCloud MockELB not set")
}

View File

@ -0,0 +1,42 @@
/*
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 awsinterfaces
import (
"context"
elb "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing"
)
type ELBAPI interface {
AddTags(ctx context.Context, params *elb.AddTagsInput, optFns ...func(*elb.Options)) (*elb.AddTagsOutput, error)
ApplySecurityGroupsToLoadBalancer(ctx context.Context, params *elb.ApplySecurityGroupsToLoadBalancerInput, optFns ...func(*elb.Options)) (*elb.ApplySecurityGroupsToLoadBalancerOutput, error)
AttachLoadBalancerToSubnets(ctx context.Context, params *elb.AttachLoadBalancerToSubnetsInput, optFns ...func(*elb.Options)) (*elb.AttachLoadBalancerToSubnetsOutput, error)
ConfigureHealthCheck(ctx context.Context, params *elb.ConfigureHealthCheckInput, optFns ...func(*elb.Options)) (*elb.ConfigureHealthCheckOutput, error)
CreateLoadBalancer(ctx context.Context, params *elb.CreateLoadBalancerInput, optFns ...func(*elb.Options)) (*elb.CreateLoadBalancerOutput, error)
CreateLoadBalancerListeners(ctx context.Context, params *elb.CreateLoadBalancerListenersInput, optFns ...func(*elb.Options)) (*elb.CreateLoadBalancerListenersOutput, error)
DeleteLoadBalancer(ctx context.Context, params *elb.DeleteLoadBalancerInput, optFns ...func(*elb.Options)) (*elb.DeleteLoadBalancerOutput, error)
DeleteLoadBalancerListeners(ctx context.Context, params *elb.DeleteLoadBalancerListenersInput, optFns ...func(*elb.Options)) (*elb.DeleteLoadBalancerListenersOutput, error)
DeregisterInstancesFromLoadBalancer(ctx context.Context, params *elb.DeregisterInstancesFromLoadBalancerInput, optFns ...func(*elb.Options)) (*elb.DeregisterInstancesFromLoadBalancerOutput, error)
DescribeInstanceHealth(ctx context.Context, params *elb.DescribeInstanceHealthInput, optFns ...func(*elb.Options)) (*elb.DescribeInstanceHealthOutput, error)
DescribeLoadBalancerAttributes(ctx context.Context, params *elb.DescribeLoadBalancerAttributesInput, optFns ...func(*elb.Options)) (*elb.DescribeLoadBalancerAttributesOutput, error)
DescribeLoadBalancers(ctx context.Context, params *elb.DescribeLoadBalancersInput, optFns ...func(*elb.Options)) (*elb.DescribeLoadBalancersOutput, error)
DescribeTags(ctx context.Context, params *elb.DescribeTagsInput, optFns ...func(*elb.Options)) (*elb.DescribeTagsOutput, error)
DetachLoadBalancerFromSubnets(ctx context.Context, params *elb.DetachLoadBalancerFromSubnetsInput, optFns ...func(*elb.Options)) (*elb.DetachLoadBalancerFromSubnetsOutput, error)
ModifyLoadBalancerAttributes(ctx context.Context, params *elb.ModifyLoadBalancerAttributesInput, optFns ...func(*elb.Options)) (*elb.ModifyLoadBalancerAttributesOutput, error)
RemoveTags(ctx context.Context, params *elb.RemoveTagsInput, optFns ...func(*elb.Options)) (*elb.RemoveTagsOutput, error)
}