Skip to content

Commit

Permalink
test(trafficrouting): add more unit-tests for ALB traffic routing to …
Browse files Browse the repository at this point in the history
…improve coverage

Signed-off-by: Armen Shakhbazian <[email protected]>
  • Loading branch information
ArenSH committed May 2, 2024
1 parent db15088 commit 4b6e4b1
Show file tree
Hide file tree
Showing 4 changed files with 225 additions and 3 deletions.
4 changes: 2 additions & 2 deletions pkg/apis/rollouts/validation/validation_references_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -955,7 +955,7 @@ func TestValidateRolloutAlbIngressesConfig(t *testing.T) {
stableIngress,
emptyIngresses,
stableIngresses,
failureCase2,
nil,
},
{
"Just .Ingress configured",
Expand All @@ -976,7 +976,7 @@ func TestValidateRolloutAlbIngressesConfig(t *testing.T) {
emptyIngress,
emptyIngresses,
stableIngresses,
nil,
failureCase1,
},
}

Expand Down
83 changes: 83 additions & 0 deletions rollout/trafficrouting/alb/alb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -721,15 +721,30 @@ func TestErrorPatchingServicePorts(t *testing.T) {
testErrorPatching(t, ro, []*networkingv1.Ingress{i, mi})
}

type fakeAWSClientBalancerFetchError struct {
Error error
DNSName string
}
type fakeAWSTargetGroupFetchError struct {
Error error
LoadBalancerARN string
}
type fakeAWSClient struct {
Ingresses []string
targetGroups []aws.TargetGroupMeta
targetGroupsErrors []fakeAWSTargetGroupFetchError
loadBalancers []*elbv2types.LoadBalancer
loadBalancerErrors []fakeAWSClientBalancerFetchError
targetHealthDescriptions []elbv2types.TargetHealthDescription
}

func (f *fakeAWSClient) GetTargetGroupMetadata(ctx context.Context, loadBalancerARN string) ([]aws.TargetGroupMeta, error) {
result := []aws.TargetGroupMeta{}
for _, lb := range f.targetGroupsErrors {
if lb.LoadBalancerARN == loadBalancerARN {
return nil, lb.Error
}
}
for _, tg := range f.targetGroups {
if slices.Contains(tg.LoadBalancerArns, loadBalancerARN) {
result = append(result, tg)
Expand All @@ -739,6 +754,11 @@ func (f *fakeAWSClient) GetTargetGroupMetadata(ctx context.Context, loadBalancer
}

func (f *fakeAWSClient) FindLoadBalancerByDNSName(ctx context.Context, dnsName string) (*elbv2types.LoadBalancer, error) {
for _, lb := range f.loadBalancerErrors {
if lb.DNSName == dnsName {
return nil, lb.Error
}
}
for _, lb := range f.loadBalancers {
if lb.DNSName != nil && *lb.DNSName == dnsName {
return lb, nil
Expand Down Expand Up @@ -1232,6 +1252,69 @@ func TestVerifyWeightMultiIngress(t *testing.T) {
assert.Equal(t, status.ALBs[0], *fakeClient.getAlbStatusMultiIngress("ingress", 0, 0))
assert.Equal(t, status.ALBs[1], *fakeClient.getAlbStatusMultiIngress("multi-ingress", 1, 2))
}

// LoadBalancer found, dns-mismatch
{
var status v1alpha1.RolloutStatus
r, fakeClient := newFakeReconciler(&status)
fakeClient.loadBalancers = []*elbv2types.LoadBalancer{
makeLoadBalancer("lb-abc123-name", "broken-dns-verify-weight-test-abc-123.us-west-2.elb.amazonaws.com"),
makeLoadBalancer("lb-multi-ingress-name", "verify-weight-multi-ingress.us-west-2.elb.amazonaws.com"),
}
fakeClient.targetGroups = []aws.TargetGroupMeta{
makeTargetGroupForBalancer("lb-multi-ingress-name", "multi-ingress-canary-tg-abc123-name", 443, 11, "default/multi-ingress-canary-svc:443"),
makeTargetGroupForBalancer("lb-multi-ingress-name", "multi-ingress-stable-tg-abc123-name", 443, 89, "default/multi-ingress-stable-svc:443"),
}

weightVerified, err := r.VerifyWeight(10)
assert.NoError(t, err)
assert.False(t, *weightVerified)
}

// LoadBalancer found, but balancer fetch failed with error
{
expectedError := k8serrors.NewBadRequest("failed to fetch load balancer")
var status v1alpha1.RolloutStatus
r, fakeClient := newFakeReconciler(&status)
fakeClient.loadBalancerErrors = []fakeAWSClientBalancerFetchError{{
DNSName: "verify-weight-test-abc-123.us-west-2.elb.amazonaws.com",
Error: expectedError,
}}
fakeClient.loadBalancers = []*elbv2types.LoadBalancer{
makeLoadBalancer("lb-multi-ingress-name", "verify-weight-multi-ingress.us-west-2.elb.amazonaws.com"),
}
fakeClient.targetGroups = []aws.TargetGroupMeta{
makeTargetGroupForBalancer("lb-multi-ingress-name", "multi-ingress-canary-tg-abc123-name", 443, 11, "default/multi-ingress-canary-svc:443"),
makeTargetGroupForBalancer("lb-multi-ingress-name", "multi-ingress-stable-tg-abc123-name", 443, 89, "default/multi-ingress-stable-svc:443"),
}

weightVerified, err := r.VerifyWeight(10)
assert.Equal(t, err, expectedError)
assert.False(t, *weightVerified)
}

// LoadBalancer found, but target group fetch failed with error
{
expectedError := k8serrors.NewBadRequest("failed to fetch target group")
var status v1alpha1.RolloutStatus
r, fakeClient := newFakeReconciler(&status)
fakeClient.loadBalancers = []*elbv2types.LoadBalancer{
makeLoadBalancer("lb-abc123-name", "verify-weight-test-abc-123.us-west-2.elb.amazonaws.com"),
makeLoadBalancer("lb-multi-ingress-name", "verify-weight-multi-ingress.us-west-2.elb.amazonaws.com"),
}
fakeClient.targetGroups = []aws.TargetGroupMeta{
makeTargetGroupForBalancer("lb-multi-ingress-name", "multi-ingress-canary-tg-abc123-name", 443, 11, "default/multi-ingress-canary-svc:443"),
makeTargetGroupForBalancer("lb-multi-ingress-name", "multi-ingress-stable-tg-abc123-name", 443, 89, "default/multi-ingress-stable-svc:443"),
}
fakeClient.targetGroupsErrors = []fakeAWSTargetGroupFetchError{{
LoadBalancerARN: *fakeClient.loadBalancers[0].LoadBalancerArn,
Error: expectedError,
}}

weightVerified, err := r.VerifyWeight(10)
assert.Equal(t, err, expectedError)
assert.False(t, *weightVerified)
}
}

func TestVerifyWeightServicePorts(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion utils/ingress/ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func SingleAlbIngressConfigured(rollout *v1alpha1.Rollout) bool {

// CheckALBTrafficRoutingHasFieldsForMultiIngressScenario returns true if either .Ingresses or .ServicePorts are set
func CheckALBTrafficRoutingHasFieldsForMultiIngressScenario(a *v1alpha1.ALBTrafficRouting) bool {
return a.Ingresses != nil || a.ServicePorts != nil
return a.Ingresses != nil
}

// GetIngressesFromALBTrafficRouting returns a list of Ingresses and their associated ports.
Expand Down
139 changes: 139 additions & 0 deletions utils/ingress/ingress_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -698,3 +698,142 @@ func TestALBHeaderBasedConditionAnnotationKey(t *testing.T) {
}
assert.Equal(t, "alb.ingress.kubernetes.io/conditions.route", ALBHeaderBasedConditionAnnotationKey(r, "route"))
}

func TestCheckALBTrafficRoutingHasFieldsForMultiIngressScenario(t *testing.T) {
res := CheckALBTrafficRoutingHasFieldsForMultiIngressScenario(&v1alpha1.ALBTrafficRouting{
Ingress: "alb-ingress",
ServicePort: 80,
})
assert.Equal(t, res, false)

res = CheckALBTrafficRoutingHasFieldsForMultiIngressScenario(&v1alpha1.ALBTrafficRouting{
Ingress: "alb-ingress",
ServicePort: 80,
Ingresses: []string{"alb-ingress", "alb-ingress-2"},
})
assert.Equal(t, res, true)

res = CheckALBTrafficRoutingHasFieldsForMultiIngressScenario(&v1alpha1.ALBTrafficRouting{
Ingress: "alb-ingress",
ServicePort: 80,
Ingresses: []string{"alb-ingress", "alb-ingress-2"},
ServicePorts: []v1alpha1.ALBIngressWithPorts{
{Ingress: "alb-ingress", ServicePorts: []int32{80, 433}},
},
})
assert.Equal(t, res, true)

res = CheckALBTrafficRoutingHasFieldsForMultiIngressScenario(&v1alpha1.ALBTrafficRouting{
Ingress: "alb-ingress",
ServicePorts: []v1alpha1.ALBIngressWithPorts{
{Ingress: "alb-ingress", ServicePorts: []int32{80, 433}},
},
})
assert.Equal(t, res, false)
}

func TestGetIngressesFromALBTrafficRouting(t *testing.T) {
res := GetIngressesFromALBTrafficRouting(&v1alpha1.ALBTrafficRouting{
Ingress: "alb-ingress",
ServicePort: 80,
})
assert.Equal(t, res, []v1alpha1.ALBIngressWithPorts{
{Ingress: "alb-ingress", ServicePorts: []int32{80}},
})

// .ServicePort is ignored when .ServicePorts has matching ingress
res = GetIngressesFromALBTrafficRouting(&v1alpha1.ALBTrafficRouting{
Ingress: "alb-ingress",
ServicePort: 80,
ServicePorts: []v1alpha1.ALBIngressWithPorts{
{Ingress: "alb-ingress", ServicePorts: []int32{80, 433}},
},
})
assert.Equal(t, res, []v1alpha1.ALBIngressWithPorts{
{Ingress: "alb-ingress", ServicePorts: []int32{80, 433}},
})

// .Ingress is ignored when .Ingresses is specified
res = GetIngressesFromALBTrafficRouting(&v1alpha1.ALBTrafficRouting{
Ingress: "alb-ingress",
ServicePort: 80,
Ingresses: []string{"alb-ingress-1", "alb-ingress-2"},
})
assert.Equal(t, res, []v1alpha1.ALBIngressWithPorts{
{Ingress: "alb-ingress-1", ServicePorts: []int32{80}},
{Ingress: "alb-ingress-2", ServicePorts: []int32{80}},
})

// Ports are taken from .ServicePorts if matching ingress is found
res = GetIngressesFromALBTrafficRouting(&v1alpha1.ALBTrafficRouting{
Ingress: "alb-ingress",
ServicePort: 80,
Ingresses: []string{"alb-ingress-1", "alb-ingress-2"},
ServicePorts: []v1alpha1.ALBIngressWithPorts{
{Ingress: "alb-ingress-2", ServicePorts: []int32{433}},
},
})
assert.Equal(t, res, []v1alpha1.ALBIngressWithPorts{
{Ingress: "alb-ingress-1", ServicePorts: []int32{80}},
{Ingress: "alb-ingress-2", ServicePorts: []int32{433}},
})
}

func TestGetAllIngressNamesFromALBTrafficRouting(t *testing.T) {
// without namespace
res := GetAllIngressNamesFromALBTrafficRouting(&v1alpha1.ALBTrafficRouting{
Ingress: "alb-ingress",
Ingresses: []string{"alb-ingress-1", "alb-ingress-2"},
ServicePorts: []v1alpha1.ALBIngressWithPorts{
{Ingress: "alb-ingress-3", ServicePorts: []int32{433}},
{Ingress: "alb-ingress-4", ServicePorts: []int32{8080}},
},
}, "")
assert.ElementsMatch(t, res, []string{
"alb-ingress",
"alb-ingress-1",
"alb-ingress-2",
"alb-ingress-3",
"alb-ingress-4",
})

// with namespace
res = GetAllIngressNamesFromALBTrafficRouting(&v1alpha1.ALBTrafficRouting{
Ingress: "alb-ingress",
// intentionally with duplicate
Ingresses: []string{"alb-ingress-1", "alb-ingress-2", "alb-ingress-2"},
ServicePorts: []v1alpha1.ALBIngressWithPorts{
{Ingress: "alb-ingress-3", ServicePorts: []int32{433}},
{Ingress: "alb-ingress-4", ServicePorts: []int32{8080}},
// intentionally duplicate
{Ingress: "alb-ingress-4", ServicePorts: []int32{433}},
},
}, "some-namespace")
assert.ElementsMatch(t, res, []string{
"some-namespace/alb-ingress",
"some-namespace/alb-ingress-1",
"some-namespace/alb-ingress-2",
"some-namespace/alb-ingress-3",
"some-namespace/alb-ingress-4",
})
}

func TestCheckALBTrafficRoutingReferencesIngress(t *testing.T) {
rollout := &v1alpha1.ALBTrafficRouting{
Ingress: "alb-ingress",
// intentionally with duplicate
Ingresses: []string{"alb-ingress-1", "alb-ingress-2"},
ServicePorts: []v1alpha1.ALBIngressWithPorts{
{Ingress: "alb-ingress-3", ServicePorts: []int32{433}},
{Ingress: "alb-ingress-4", ServicePorts: []int32{8080}},
},
}
assert.Equal(t, true, CheckALBTrafficRoutingReferencesIngress(rollout, "alb-ingress"))
assert.Equal(t, true, CheckALBTrafficRoutingReferencesIngress(rollout, "alb-ingress-1"))
assert.Equal(t, true, CheckALBTrafficRoutingReferencesIngress(rollout, "alb-ingress-2"))
assert.Equal(t, true, CheckALBTrafficRoutingReferencesIngress(rollout, "alb-ingress-3"))
assert.Equal(t, true, CheckALBTrafficRoutingReferencesIngress(rollout, "alb-ingress-4"))

assert.Equal(t, false, CheckALBTrafficRoutingReferencesIngress(rollout, "alb-ingress-5"))
assert.Equal(t, false, CheckALBTrafficRoutingReferencesIngress(rollout, ""))
}

0 comments on commit 4b6e4b1

Please sign in to comment.