mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-02 00:07:50 +00:00
Accept healthy instances in list of active instances
Fixes GH #79581 Healthy instances have a nil Reason associated with their target health, so without this, actualIDs ends up as empty (well, without healthy instance IDs in it, anyway). As a result, any instances not present in the instances parameter are perceived to be already out of the target group, and are thus never deregistered. Add tests for node registration/deregistration Make sure that when EnsureLoadBalancer is called with a new set of nodes, old members of the target group are deregistered, and new members in the new set are registered Tests GH #79581 Address golint grievances Run gazelle to update AWS cloud provider dependencies Fix typecheck error
This commit is contained in:
parent
6e38a0f46e
commit
a59a91d415
@ -86,13 +86,16 @@ go_test(
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||
"//staging/src/k8s.io/cloud-provider/volume:go_default_library",
|
||||
"//vendor/github.com/aws/aws-sdk-go/aws:go_default_library",
|
||||
"//vendor/github.com/aws/aws-sdk-go/aws/awserr:go_default_library",
|
||||
"//vendor/github.com/aws/aws-sdk-go/service/ec2:go_default_library",
|
||||
"//vendor/github.com/aws/aws-sdk-go/service/elb:go_default_library",
|
||||
"//vendor/github.com/aws/aws-sdk-go/service/elbv2:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/mock:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/require:go_default_library",
|
||||
|
@ -603,7 +603,9 @@ func (c *Cloud) ensureTargetGroup(targetGroup *elbv2.TargetGroup, serviceName ty
|
||||
}
|
||||
actualIDs := []string{}
|
||||
for _, healthDescription := range healthResponse.TargetHealthDescriptions {
|
||||
if healthDescription.TargetHealth.Reason != nil {
|
||||
if aws.StringValue(healthDescription.TargetHealth.State) == elbv2.TargetHealthStateEnumHealthy {
|
||||
actualIDs = append(actualIDs, *healthDescription.Target.Id)
|
||||
} else if healthDescription.TargetHealth.Reason != nil {
|
||||
switch aws.StringValue(healthDescription.TargetHealth.Reason) {
|
||||
case elbv2.TargetHealthReasonEnumTargetDeregistrationInProgress:
|
||||
// We don't need to count this instance in service if it is
|
||||
|
@ -22,21 +22,25 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/aws/aws-sdk-go/service/elb"
|
||||
"github.com/aws/aws-sdk-go/service/elbv2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
@ -1708,7 +1712,6 @@ func TestAddLoadBalancerTags(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEnsureLoadBalancerHealthCheck(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
annotations map[string]string
|
||||
@ -1974,6 +1977,579 @@ func informerNotSynced() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type MockedFakeELBV2 struct {
|
||||
LoadBalancers []*elbv2.LoadBalancer
|
||||
TargetGroups []*elbv2.TargetGroup
|
||||
Listeners []*elbv2.Listener
|
||||
|
||||
// keys on all of these maps are ARNs
|
||||
LoadBalancerAttributes map[string]map[string]string
|
||||
Tags map[string][]elbv2.Tag
|
||||
RegisteredInstances map[string][]string // value is list of instance IDs
|
||||
}
|
||||
|
||||
func (m *MockedFakeELBV2) AddTags(request *elbv2.AddTagsInput) (*elbv2.AddTagsOutput, error) {
|
||||
for _, arn := range request.ResourceArns {
|
||||
for _, tag := range request.Tags {
|
||||
m.Tags[aws.StringValue(arn)] = append(m.Tags[aws.StringValue(arn)], *tag)
|
||||
}
|
||||
}
|
||||
|
||||
return &elbv2.AddTagsOutput{}, nil
|
||||
}
|
||||
|
||||
func (m *MockedFakeELBV2) CreateLoadBalancer(request *elbv2.CreateLoadBalancerInput) (*elbv2.CreateLoadBalancerOutput, error) {
|
||||
accountID := 123456789
|
||||
arn := fmt.Sprintf("arn:aws:elasticloadbalancing:us-east-1:%d:loadbalancer/net/%x/%x",
|
||||
accountID,
|
||||
rand.Uint64(),
|
||||
rand.Uint32())
|
||||
|
||||
newLB := &elbv2.LoadBalancer{
|
||||
LoadBalancerArn: aws.String(arn),
|
||||
LoadBalancerName: request.Name,
|
||||
Type: aws.String(elbv2.LoadBalancerTypeEnumNetwork),
|
||||
VpcId: aws.String("vpc-abc123def456abc78"),
|
||||
}
|
||||
m.LoadBalancers = append(m.LoadBalancers, newLB)
|
||||
|
||||
return &elbv2.CreateLoadBalancerOutput{
|
||||
LoadBalancers: []*elbv2.LoadBalancer{newLB},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *MockedFakeELBV2) DescribeLoadBalancers(request *elbv2.DescribeLoadBalancersInput) (*elbv2.DescribeLoadBalancersOutput, error) {
|
||||
findMeNames := make(map[string]bool)
|
||||
for _, name := range request.Names {
|
||||
findMeNames[aws.StringValue(name)] = true
|
||||
}
|
||||
|
||||
findMeARNs := make(map[string]bool)
|
||||
for _, arn := range request.LoadBalancerArns {
|
||||
findMeARNs[aws.StringValue(arn)] = true
|
||||
}
|
||||
|
||||
result := []*elbv2.LoadBalancer{}
|
||||
|
||||
for _, lb := range m.LoadBalancers {
|
||||
if _, present := findMeNames[aws.StringValue(lb.LoadBalancerName)]; present {
|
||||
result = append(result, lb)
|
||||
delete(findMeNames, aws.StringValue(lb.LoadBalancerName))
|
||||
} else if _, present := findMeARNs[aws.StringValue(lb.LoadBalancerArn)]; present {
|
||||
result = append(result, lb)
|
||||
delete(findMeARNs, aws.StringValue(lb.LoadBalancerArn))
|
||||
}
|
||||
}
|
||||
|
||||
if len(findMeNames) > 0 || len(findMeARNs) > 0 {
|
||||
return nil, awserr.New(elbv2.ErrCodeLoadBalancerNotFoundException, "not found", nil)
|
||||
}
|
||||
|
||||
return &elbv2.DescribeLoadBalancersOutput{
|
||||
LoadBalancers: result,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *MockedFakeELBV2) DeleteLoadBalancer(*elbv2.DeleteLoadBalancerInput) (*elbv2.DeleteLoadBalancerOutput, error) {
|
||||
panic("Not implemented")
|
||||
}
|
||||
|
||||
func (m *MockedFakeELBV2) ModifyLoadBalancerAttributes(request *elbv2.ModifyLoadBalancerAttributesInput) (*elbv2.ModifyLoadBalancerAttributesOutput, error) {
|
||||
attrMap, present := m.LoadBalancerAttributes[aws.StringValue(request.LoadBalancerArn)]
|
||||
|
||||
if !present {
|
||||
attrMap = make(map[string]string)
|
||||
m.LoadBalancerAttributes[aws.StringValue(request.LoadBalancerArn)] = attrMap
|
||||
}
|
||||
|
||||
for _, attr := range request.Attributes {
|
||||
attrMap[aws.StringValue(attr.Key)] = aws.StringValue(attr.Value)
|
||||
}
|
||||
|
||||
return &elbv2.ModifyLoadBalancerAttributesOutput{
|
||||
Attributes: request.Attributes,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *MockedFakeELBV2) DescribeLoadBalancerAttributes(request *elbv2.DescribeLoadBalancerAttributesInput) (*elbv2.DescribeLoadBalancerAttributesOutput, error) {
|
||||
attrs := []*elbv2.LoadBalancerAttribute{}
|
||||
|
||||
if lbAttrs, present := m.LoadBalancerAttributes[aws.StringValue(request.LoadBalancerArn)]; present {
|
||||
for key, value := range lbAttrs {
|
||||
attrs = append(attrs, &elbv2.LoadBalancerAttribute{
|
||||
Key: aws.String(key),
|
||||
Value: aws.String(value),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return &elbv2.DescribeLoadBalancerAttributesOutput{
|
||||
Attributes: attrs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *MockedFakeELBV2) CreateTargetGroup(request *elbv2.CreateTargetGroupInput) (*elbv2.CreateTargetGroupOutput, error) {
|
||||
accountID := 123456789
|
||||
arn := fmt.Sprintf("arn:aws:elasticloadbalancing:us-east-1:%d:targetgroup/%x/%x",
|
||||
accountID,
|
||||
rand.Uint64(),
|
||||
rand.Uint32())
|
||||
|
||||
newTG := &elbv2.TargetGroup{
|
||||
TargetGroupArn: aws.String(arn),
|
||||
TargetGroupName: request.Name,
|
||||
Port: request.Port,
|
||||
Protocol: request.Protocol,
|
||||
}
|
||||
|
||||
m.TargetGroups = append(m.TargetGroups, newTG)
|
||||
|
||||
return &elbv2.CreateTargetGroupOutput{
|
||||
TargetGroups: []*elbv2.TargetGroup{newTG},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *MockedFakeELBV2) DescribeTargetGroups(request *elbv2.DescribeTargetGroupsInput) (*elbv2.DescribeTargetGroupsOutput, error) {
|
||||
var targetGroups []*elbv2.TargetGroup
|
||||
|
||||
if request.LoadBalancerArn != nil {
|
||||
targetGroups = []*elbv2.TargetGroup{}
|
||||
|
||||
for _, tg := range m.TargetGroups {
|
||||
for _, lbArn := range tg.LoadBalancerArns {
|
||||
if aws.StringValue(lbArn) == aws.StringValue(request.LoadBalancerArn) {
|
||||
targetGroups = append(targetGroups, tg)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if len(request.Names) != 0 {
|
||||
targetGroups = []*elbv2.TargetGroup{}
|
||||
|
||||
for _, tg := range m.TargetGroups {
|
||||
for _, name := range request.Names {
|
||||
if aws.StringValue(tg.TargetGroupName) == aws.StringValue(name) {
|
||||
targetGroups = append(targetGroups, tg)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if len(request.TargetGroupArns) != 0 {
|
||||
targetGroups = []*elbv2.TargetGroup{}
|
||||
|
||||
for _, tg := range m.TargetGroups {
|
||||
for _, arn := range request.TargetGroupArns {
|
||||
if aws.StringValue(tg.TargetGroupArn) == aws.StringValue(arn) {
|
||||
targetGroups = append(targetGroups, tg)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
targetGroups = m.TargetGroups
|
||||
}
|
||||
|
||||
return &elbv2.DescribeTargetGroupsOutput{
|
||||
TargetGroups: targetGroups,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *MockedFakeELBV2) ModifyTargetGroup(request *elbv2.ModifyTargetGroupInput) (*elbv2.ModifyTargetGroupOutput, error) {
|
||||
var matchingTargetGroup *elbv2.TargetGroup
|
||||
dirtyGroups := []*elbv2.TargetGroup{}
|
||||
|
||||
for _, tg := range m.TargetGroups {
|
||||
if aws.StringValue(tg.TargetGroupArn) == aws.StringValue(request.TargetGroupArn) {
|
||||
matchingTargetGroup = tg
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if matchingTargetGroup != nil {
|
||||
dirtyGroups = append(dirtyGroups, matchingTargetGroup)
|
||||
|
||||
if request.HealthCheckEnabled != nil {
|
||||
matchingTargetGroup.HealthCheckEnabled = request.HealthCheckEnabled
|
||||
}
|
||||
if request.HealthCheckIntervalSeconds != nil {
|
||||
matchingTargetGroup.HealthCheckIntervalSeconds = request.HealthCheckIntervalSeconds
|
||||
}
|
||||
if request.HealthCheckPath != nil {
|
||||
matchingTargetGroup.HealthCheckPath = request.HealthCheckPath
|
||||
}
|
||||
if request.HealthCheckPort != nil {
|
||||
matchingTargetGroup.HealthCheckPort = request.HealthCheckPort
|
||||
}
|
||||
if request.HealthCheckProtocol != nil {
|
||||
matchingTargetGroup.HealthCheckProtocol = request.HealthCheckProtocol
|
||||
}
|
||||
if request.HealthCheckTimeoutSeconds != nil {
|
||||
matchingTargetGroup.HealthCheckTimeoutSeconds = request.HealthCheckTimeoutSeconds
|
||||
}
|
||||
if request.HealthyThresholdCount != nil {
|
||||
matchingTargetGroup.HealthyThresholdCount = request.HealthyThresholdCount
|
||||
}
|
||||
if request.Matcher != nil {
|
||||
matchingTargetGroup.Matcher = request.Matcher
|
||||
}
|
||||
if request.UnhealthyThresholdCount != nil {
|
||||
matchingTargetGroup.UnhealthyThresholdCount = request.UnhealthyThresholdCount
|
||||
}
|
||||
}
|
||||
|
||||
return &elbv2.ModifyTargetGroupOutput{
|
||||
TargetGroups: dirtyGroups,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *MockedFakeELBV2) DeleteTargetGroup(request *elbv2.DeleteTargetGroupInput) (*elbv2.DeleteTargetGroupOutput, error) {
|
||||
newTargetGroups := []*elbv2.TargetGroup{}
|
||||
|
||||
for _, tg := range m.TargetGroups {
|
||||
if aws.StringValue(tg.TargetGroupArn) != aws.StringValue(request.TargetGroupArn) {
|
||||
newTargetGroups = append(newTargetGroups, tg)
|
||||
}
|
||||
}
|
||||
|
||||
m.TargetGroups = newTargetGroups
|
||||
|
||||
delete(m.RegisteredInstances, aws.StringValue(request.TargetGroupArn))
|
||||
|
||||
return &elbv2.DeleteTargetGroupOutput{}, nil
|
||||
}
|
||||
|
||||
func (m *MockedFakeELBV2) DescribeTargetHealth(request *elbv2.DescribeTargetHealthInput) (*elbv2.DescribeTargetHealthOutput, error) {
|
||||
healthDescriptions := []*elbv2.TargetHealthDescription{}
|
||||
|
||||
var matchingTargetGroup *elbv2.TargetGroup
|
||||
|
||||
for _, tg := range m.TargetGroups {
|
||||
if aws.StringValue(tg.TargetGroupArn) == aws.StringValue(request.TargetGroupArn) {
|
||||
matchingTargetGroup = tg
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if registeredTargets, present := m.RegisteredInstances[aws.StringValue(request.TargetGroupArn)]; present {
|
||||
for _, target := range registeredTargets {
|
||||
healthDescriptions = append(healthDescriptions, &elbv2.TargetHealthDescription{
|
||||
HealthCheckPort: matchingTargetGroup.HealthCheckPort,
|
||||
Target: &elbv2.TargetDescription{
|
||||
Id: aws.String(target),
|
||||
Port: matchingTargetGroup.Port,
|
||||
},
|
||||
TargetHealth: &elbv2.TargetHealth{
|
||||
State: aws.String("healthy"),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return &elbv2.DescribeTargetHealthOutput{
|
||||
TargetHealthDescriptions: healthDescriptions,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *MockedFakeELBV2) DescribeTargetGroupAttributes(*elbv2.DescribeTargetGroupAttributesInput) (*elbv2.DescribeTargetGroupAttributesOutput, error) {
|
||||
panic("Not implemented")
|
||||
}
|
||||
|
||||
func (m *MockedFakeELBV2) ModifyTargetGroupAttributes(*elbv2.ModifyTargetGroupAttributesInput) (*elbv2.ModifyTargetGroupAttributesOutput, error) {
|
||||
panic("Not implemented")
|
||||
}
|
||||
|
||||
func (m *MockedFakeELBV2) RegisterTargets(request *elbv2.RegisterTargetsInput) (*elbv2.RegisterTargetsOutput, error) {
|
||||
arn := aws.StringValue(request.TargetGroupArn)
|
||||
alreadyExists := make(map[string]bool)
|
||||
for _, targetID := range m.RegisteredInstances[arn] {
|
||||
alreadyExists[targetID] = true
|
||||
}
|
||||
for _, target := range request.Targets {
|
||||
if !alreadyExists[aws.StringValue(target.Id)] {
|
||||
m.RegisteredInstances[arn] = append(m.RegisteredInstances[arn], aws.StringValue(target.Id))
|
||||
}
|
||||
}
|
||||
return &elbv2.RegisterTargetsOutput{}, nil
|
||||
}
|
||||
|
||||
func (m *MockedFakeELBV2) DeregisterTargets(request *elbv2.DeregisterTargetsInput) (*elbv2.DeregisterTargetsOutput, error) {
|
||||
removeMe := make(map[string]bool)
|
||||
|
||||
for _, target := range request.Targets {
|
||||
removeMe[aws.StringValue(target.Id)] = true
|
||||
}
|
||||
newRegisteredInstancesForArn := []string{}
|
||||
for _, targetID := range m.RegisteredInstances[aws.StringValue(request.TargetGroupArn)] {
|
||||
if !removeMe[targetID] {
|
||||
newRegisteredInstancesForArn = append(newRegisteredInstancesForArn, targetID)
|
||||
}
|
||||
}
|
||||
m.RegisteredInstances[aws.StringValue(request.TargetGroupArn)] = newRegisteredInstancesForArn
|
||||
|
||||
return &elbv2.DeregisterTargetsOutput{}, nil
|
||||
}
|
||||
|
||||
func (m *MockedFakeELBV2) CreateListener(request *elbv2.CreateListenerInput) (*elbv2.CreateListenerOutput, error) {
|
||||
accountID := 123456789
|
||||
arn := fmt.Sprintf("arn:aws:elasticloadbalancing:us-east-1:%d:listener/net/%x/%x/%x",
|
||||
accountID,
|
||||
rand.Uint64(),
|
||||
rand.Uint32(),
|
||||
rand.Uint32())
|
||||
|
||||
newListener := &elbv2.Listener{
|
||||
ListenerArn: aws.String(arn),
|
||||
Port: request.Port,
|
||||
Protocol: request.Protocol,
|
||||
DefaultActions: request.DefaultActions,
|
||||
LoadBalancerArn: request.LoadBalancerArn,
|
||||
}
|
||||
|
||||
m.Listeners = append(m.Listeners, newListener)
|
||||
|
||||
for _, tg := range m.TargetGroups {
|
||||
for _, action := range request.DefaultActions {
|
||||
if aws.StringValue(action.TargetGroupArn) == aws.StringValue(tg.TargetGroupArn) {
|
||||
tg.LoadBalancerArns = append(tg.LoadBalancerArns, request.LoadBalancerArn)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &elbv2.CreateListenerOutput{
|
||||
Listeners: []*elbv2.Listener{newListener},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *MockedFakeELBV2) DescribeListeners(request *elbv2.DescribeListenersInput) (*elbv2.DescribeListenersOutput, error) {
|
||||
if len(request.ListenerArns) == 0 && request.LoadBalancerArn == nil {
|
||||
return &elbv2.DescribeListenersOutput{
|
||||
Listeners: m.Listeners,
|
||||
}, nil
|
||||
} else if len(request.ListenerArns) == 0 {
|
||||
listeners := []*elbv2.Listener{}
|
||||
|
||||
for _, lb := range m.Listeners {
|
||||
if aws.StringValue(lb.LoadBalancerArn) == aws.StringValue(request.LoadBalancerArn) {
|
||||
listeners = append(listeners, lb)
|
||||
}
|
||||
}
|
||||
|
||||
return &elbv2.DescribeListenersOutput{
|
||||
Listeners: listeners,
|
||||
}, nil
|
||||
}
|
||||
panic("Not implemented")
|
||||
}
|
||||
|
||||
func (m *MockedFakeELBV2) DeleteListener(*elbv2.DeleteListenerInput) (*elbv2.DeleteListenerOutput, error) {
|
||||
panic("Not implemented")
|
||||
}
|
||||
|
||||
func (m *MockedFakeELBV2) ModifyListener(request *elbv2.ModifyListenerInput) (*elbv2.ModifyListenerOutput, error) {
|
||||
modifiedListeners := []*elbv2.Listener{}
|
||||
|
||||
for _, listener := range m.Listeners {
|
||||
if aws.StringValue(listener.ListenerArn) == aws.StringValue(request.ListenerArn) {
|
||||
if request.DefaultActions != nil {
|
||||
// for each old action, find the corresponding target group, and remove the listener's LB ARN from its list
|
||||
for _, action := range listener.DefaultActions {
|
||||
var targetGroupForAction *elbv2.TargetGroup
|
||||
|
||||
for _, tg := range m.TargetGroups {
|
||||
if aws.StringValue(action.TargetGroupArn) == aws.StringValue(tg.TargetGroupArn) {
|
||||
targetGroupForAction = tg
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if targetGroupForAction != nil {
|
||||
newLoadBalancerARNs := []*string{}
|
||||
for _, lbArn := range targetGroupForAction.LoadBalancerArns {
|
||||
if aws.StringValue(lbArn) != aws.StringValue(listener.LoadBalancerArn) {
|
||||
newLoadBalancerARNs = append(newLoadBalancerARNs, lbArn)
|
||||
}
|
||||
}
|
||||
|
||||
targetGroupForAction.LoadBalancerArns = newLoadBalancerARNs
|
||||
}
|
||||
}
|
||||
|
||||
listener.DefaultActions = request.DefaultActions
|
||||
|
||||
// for each new action, add the listener's LB ARN to that action's target groups' lists
|
||||
for _, action := range request.DefaultActions {
|
||||
var targetGroupForAction *elbv2.TargetGroup
|
||||
|
||||
for _, tg := range m.TargetGroups {
|
||||
if aws.StringValue(action.TargetGroupArn) == aws.StringValue(tg.TargetGroupArn) {
|
||||
targetGroupForAction = tg
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if targetGroupForAction != nil {
|
||||
targetGroupForAction.LoadBalancerArns = append(targetGroupForAction.LoadBalancerArns, listener.LoadBalancerArn)
|
||||
}
|
||||
}
|
||||
}
|
||||
if request.Port != nil {
|
||||
listener.Port = request.Port
|
||||
}
|
||||
if request.Protocol != nil {
|
||||
listener.Protocol = request.Protocol
|
||||
}
|
||||
|
||||
modifiedListeners = append(modifiedListeners, listener)
|
||||
}
|
||||
}
|
||||
|
||||
return &elbv2.ModifyListenerOutput{
|
||||
Listeners: modifiedListeners,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *MockedFakeELBV2) WaitUntilLoadBalancersDeleted(*elbv2.DescribeLoadBalancersInput) error {
|
||||
panic("Not implemented")
|
||||
}
|
||||
|
||||
func (m *MockedFakeEC2) maybeExpectDescribeSecurityGroups(clusterID, groupName string) {
|
||||
tags := []*ec2.Tag{
|
||||
{Key: aws.String(TagNameKubernetesClusterLegacy), Value: aws.String(clusterID)},
|
||||
{Key: aws.String(fmt.Sprintf("%s%s", TagNameKubernetesClusterPrefix, clusterID)), Value: aws.String(ResourceLifecycleOwned)},
|
||||
}
|
||||
|
||||
m.On("DescribeSecurityGroups", &ec2.DescribeSecurityGroupsInput{Filters: []*ec2.Filter{
|
||||
newEc2Filter("group-name", groupName),
|
||||
newEc2Filter("vpc-id", ""),
|
||||
}}).Maybe().Return([]*ec2.SecurityGroup{{Tags: tags}})
|
||||
|
||||
m.On("DescribeSecurityGroups", &ec2.DescribeSecurityGroupsInput{}).Maybe().Return([]*ec2.SecurityGroup{{Tags: tags}})
|
||||
}
|
||||
|
||||
func TestNLBNodeRegistration(t *testing.T) {
|
||||
awsServices := newMockedFakeAWSServices(TestClusterID)
|
||||
awsServices.elbv2 = &MockedFakeELBV2{Tags: make(map[string][]elbv2.Tag), RegisteredInstances: make(map[string][]string), LoadBalancerAttributes: make(map[string]map[string]string)}
|
||||
c, _ := newAWSCloud(CloudConfig{}, awsServices)
|
||||
|
||||
awsServices.ec2.(*MockedFakeEC2).Subnets = []*ec2.Subnet{
|
||||
{
|
||||
AvailabilityZone: aws.String("us-west-2a"),
|
||||
SubnetId: aws.String("subnet-abc123de"),
|
||||
Tags: []*ec2.Tag{
|
||||
{
|
||||
Key: aws.String(c.tagging.clusterTagKey()),
|
||||
Value: aws.String("owned"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
awsServices.ec2.(*MockedFakeEC2).RouteTables = []*ec2.RouteTable{
|
||||
{
|
||||
Associations: []*ec2.RouteTableAssociation{
|
||||
{
|
||||
Main: aws.Bool(true),
|
||||
RouteTableAssociationId: aws.String("rtbassoc-abc123def456abc78"),
|
||||
RouteTableId: aws.String("rtb-abc123def456abc78"),
|
||||
SubnetId: aws.String("subnet-abc123de"),
|
||||
},
|
||||
},
|
||||
RouteTableId: aws.String("rtb-abc123def456abc78"),
|
||||
Routes: []*ec2.Route{
|
||||
{
|
||||
DestinationCidrBlock: aws.String("0.0.0.0/0"),
|
||||
GatewayId: aws.String("igw-abc123def456abc78"),
|
||||
State: aws.String("active"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
awsServices.ec2.(*MockedFakeEC2).maybeExpectDescribeSecurityGroups(TestClusterID, "k8s-elb-aid")
|
||||
|
||||
nodes := []*v1.Node{makeNamedNode(awsServices, 0, "a"), makeNamedNode(awsServices, 1, "b"), makeNamedNode(awsServices, 2, "c")}
|
||||
|
||||
fauxService := &v1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "myservice",
|
||||
UID: "id",
|
||||
Annotations: map[string]string{
|
||||
"service.beta.kubernetes.io/aws-load-balancer-type": "nlb",
|
||||
},
|
||||
},
|
||||
Spec: v1.ServiceSpec{
|
||||
Ports: []v1.ServicePort{
|
||||
{
|
||||
Name: "http",
|
||||
Port: 8080,
|
||||
NodePort: 31173,
|
||||
TargetPort: intstr.FromInt(31173),
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
SessionAffinity: v1.ServiceAffinityNone,
|
||||
},
|
||||
}
|
||||
|
||||
_, err := c.EnsureLoadBalancer(context.TODO(), TestClusterName, fauxService, nodes)
|
||||
if err != nil {
|
||||
t.Errorf("EnsureLoadBalancer returned an error: %v", err)
|
||||
}
|
||||
for _, instances := range awsServices.elbv2.(*MockedFakeELBV2).RegisteredInstances {
|
||||
if len(instances) != 3 {
|
||||
t.Errorf("Expected 3 nodes registered with target group, saw %d", len(instances))
|
||||
}
|
||||
}
|
||||
|
||||
_, err = c.EnsureLoadBalancer(context.TODO(), TestClusterName, fauxService, nodes[:2])
|
||||
if err != nil {
|
||||
t.Errorf("EnsureLoadBalancer returned an error: %v", err)
|
||||
}
|
||||
for _, instances := range awsServices.elbv2.(*MockedFakeELBV2).RegisteredInstances {
|
||||
if len(instances) != 2 {
|
||||
t.Errorf("Expected 2 nodes registered with target group, saw %d", len(instances))
|
||||
}
|
||||
}
|
||||
|
||||
_, err = c.EnsureLoadBalancer(context.TODO(), TestClusterName, fauxService, nodes)
|
||||
if err != nil {
|
||||
t.Errorf("EnsureLoadBalancer returned an error: %v", err)
|
||||
}
|
||||
for _, instances := range awsServices.elbv2.(*MockedFakeELBV2).RegisteredInstances {
|
||||
if len(instances) != 3 {
|
||||
t.Errorf("Expected 3 nodes registered with target group, saw %d", len(instances))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func makeNamedNode(s *FakeAWSServices, offset int, name string) *v1.Node {
|
||||
instanceID := fmt.Sprintf("i-%x", int64(0x02bce90670bb0c7cd)+int64(offset))
|
||||
instance := &ec2.Instance{}
|
||||
instance.InstanceId = aws.String(instanceID)
|
||||
instance.Placement = &ec2.Placement{
|
||||
AvailabilityZone: aws.String("us-east-1c"),
|
||||
}
|
||||
instance.PrivateDnsName = aws.String(fmt.Sprintf("ip-172-20-0-%d.ec2.internal", 101+offset))
|
||||
instance.PrivateIpAddress = aws.String(fmt.Sprintf("192.168.0.%d", 1+offset))
|
||||
|
||||
var tag ec2.Tag
|
||||
tag.Key = aws.String(TagNameKubernetesClusterLegacy)
|
||||
tag.Value = aws.String(TestClusterID)
|
||||
instance.Tags = []*ec2.Tag{&tag}
|
||||
|
||||
s.instances = append(s.instances, instance)
|
||||
|
||||
testProviderID := "aws:///us-east-1c/" + instanceID
|
||||
return &v1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
},
|
||||
Spec: v1.NodeSpec{
|
||||
ProviderID: testProviderID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newMockedFakeAWSServices(id string) *FakeAWSServices {
|
||||
s := NewFakeAWSServices(id)
|
||||
s.ec2 = &MockedFakeEC2{FakeEC2Impl: s.ec2.(*FakeEC2Impl)}
|
||||
|
Loading…
Reference in New Issue
Block a user