@@ -2,11 +2,17 @@ package model
22
33import (
44 "context"
5+ "fmt"
56 awssdk "github.com/aws/aws-sdk-go-v2/aws"
67 elbv2sdk "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2"
78 elbv2types "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2/types"
9+ "github.com/google/go-cmp/cmp"
10+ "github.com/google/go-cmp/cmp/cmpopts"
11+ corev1 "k8s.io/api/core/v1"
812 "reflect"
913 "sigs.k8s.io/aws-load-balancer-controller/pkg/aws/services"
14+ "sigs.k8s.io/aws-load-balancer-controller/pkg/gateway/routeutils"
15+ coremodel "sigs.k8s.io/aws-load-balancer-controller/pkg/model/core"
1016 "sigs.k8s.io/aws-load-balancer-controller/pkg/networking"
1117 "strings"
1218 "testing"
@@ -16,7 +22,7 @@ import (
1622 "github.com/pkg/errors"
1723 "github.com/stretchr/testify/assert"
1824 elbv2gw "sigs.k8s.io/aws-load-balancer-controller/apis/gateway/v1beta1"
19- certs "sigs.k8s.io/aws-load-balancer-controller/pkg/certs"
25+ "sigs.k8s.io/aws-load-balancer-controller/pkg/certs"
2026 elbv2model "sigs.k8s.io/aws-load-balancer-controller/pkg/model/elbv2"
2127 gwv1 "sigs.k8s.io/gateway-api/apis/v1"
2228)
@@ -1083,3 +1089,191 @@ func Test_buildMutualAuthenticationAttributes(t *testing.T) {
10831089 })
10841090 }
10851091}
1092+
1093+ func TestBuildListenerRules (t * testing.T ) {
1094+ testCases := []struct {
1095+ name string
1096+ sgOutput securityGroupOutput
1097+ ipAddressType elbv2model.IPAddressType
1098+ port int32
1099+ routes map [int32 ][]routeutils.RouteDescriptor
1100+
1101+ expectedRules []* elbv2model.ListenerRuleSpec
1102+ expectedTags map [string ]string
1103+ tagErr error
1104+ }{
1105+ {
1106+ name : "no backends should result in 503 fixed response" ,
1107+ port : 80 ,
1108+ ipAddressType : elbv2model .IPAddressTypeIPV4 ,
1109+ sgOutput : securityGroupOutput {
1110+ backendSecurityGroupToken : coremodel .LiteralStringToken ("sg-B" ),
1111+ },
1112+ routes : map [int32 ][]routeutils.RouteDescriptor {
1113+ 80 : {
1114+ & routeutils.MockRoute {
1115+ Kind : routeutils .HTTPRouteKind ,
1116+ Name : "my-route" ,
1117+ Namespace : "my-route-ns" ,
1118+ Rules : []routeutils.RouteRule {
1119+ & routeutils.MockRule {
1120+ RawRule : & gwv1.HTTPRouteRule {
1121+ Matches : []gwv1.HTTPRouteMatch {
1122+ {
1123+ Path : & gwv1.HTTPPathMatch {
1124+ Type : (* gwv1 .PathMatchType )(awssdk .String ("PathPrefix" )),
1125+ Value : awssdk .String ("/" ),
1126+ },
1127+ },
1128+ },
1129+ },
1130+ },
1131+ },
1132+ },
1133+ },
1134+ },
1135+ expectedRules : []* elbv2model.ListenerRuleSpec {
1136+ {
1137+ Priority : 1 ,
1138+ Actions : []elbv2model.Action {
1139+ {
1140+ Type : "fixed-response" ,
1141+ FixedResponseConfig : & elbv2model.FixedResponseActionConfig {
1142+ ContentType : awssdk .String ("text/plain" ),
1143+ StatusCode : "503" ,
1144+ },
1145+ },
1146+ },
1147+ Conditions : []elbv2model.RuleCondition {
1148+ {
1149+ Field : "path-pattern" ,
1150+ PathPatternConfig : & elbv2model.PathPatternConditionConfig {
1151+ Values : []string {"/*" },
1152+ },
1153+ },
1154+ },
1155+ },
1156+ },
1157+ },
1158+ {
1159+ name : "backends should result in forward action generated" ,
1160+ port : 80 ,
1161+ ipAddressType : elbv2model .IPAddressTypeIPV4 ,
1162+ sgOutput : securityGroupOutput {
1163+ backendSecurityGroupToken : coremodel .LiteralStringToken ("sg-B" ),
1164+ },
1165+ routes : map [int32 ][]routeutils.RouteDescriptor {
1166+ 80 : {
1167+ & routeutils.MockRoute {
1168+ Kind : routeutils .HTTPRouteKind ,
1169+ Name : "my-route" ,
1170+ Namespace : "my-route-ns" ,
1171+ Rules : []routeutils.RouteRule {
1172+ & routeutils.MockRule {
1173+ RawRule : & gwv1.HTTPRouteRule {
1174+ Matches : []gwv1.HTTPRouteMatch {
1175+ {
1176+ Path : & gwv1.HTTPPathMatch {
1177+ Type : (* gwv1 .PathMatchType )(awssdk .String ("PathPrefix" )),
1178+ Value : awssdk .String ("/" ),
1179+ },
1180+ },
1181+ },
1182+ },
1183+ BackendRefs : []routeutils.Backend {
1184+ {
1185+ Service : & corev1.Service {},
1186+ ServicePort : & corev1.ServicePort {Name : "svcport" },
1187+ Weight : 1 ,
1188+ },
1189+ },
1190+ },
1191+ },
1192+ },
1193+ },
1194+ },
1195+ expectedRules : []* elbv2model.ListenerRuleSpec {
1196+ {
1197+ Priority : 1 ,
1198+ Actions : []elbv2model.Action {
1199+ {
1200+ Type : "forward" ,
1201+ ForwardConfig : & elbv2model.ForwardActionConfig {
1202+ // cmp can't compare the TG ARN, so don't inject it.
1203+ TargetGroups : []elbv2model.TargetGroupTuple {
1204+ {
1205+ Weight : awssdk .Int32 (1 ),
1206+ },
1207+ },
1208+ },
1209+ },
1210+ },
1211+ Conditions : []elbv2model.RuleCondition {
1212+ {
1213+ Field : "path-pattern" ,
1214+ PathPatternConfig : & elbv2model.PathPatternConditionConfig {
1215+ Values : []string {"/*" },
1216+ },
1217+ },
1218+ },
1219+ },
1220+ },
1221+ },
1222+ }
1223+
1224+ for _ , tc := range testCases {
1225+ t .Run (tc .name , func (t * testing.T ) {
1226+ stack := coremodel .NewDefaultStack (coremodel.StackID {Namespace : "namespace" , Name : "name" })
1227+ mockTagger := & mockTagHelper {
1228+ tags : tc .expectedTags ,
1229+ err : tc .tagErr ,
1230+ }
1231+
1232+ mockTgBuilder := & MockTargetGroupBuilder {
1233+ tgs : []* elbv2model.TargetGroup {
1234+ {
1235+ ResourceMeta : coremodel .NewResourceMeta (stack , "AWS::ElasticLoadBalancingV2::TargetGroup" , "id-1" ),
1236+ },
1237+ },
1238+ }
1239+
1240+ builder := & listenerBuilderImpl {
1241+ tagHelper : mockTagger ,
1242+ tgBuilder : mockTgBuilder ,
1243+ }
1244+
1245+ err := builder .buildListenerRules (stack , & elbv2model.Listener {}, tc .ipAddressType , tc .sgOutput , & gwv1.Gateway {}, tc .port , elbv2gw.LoadBalancerConfiguration {}, tc .routes )
1246+ assert .NoError (t , err )
1247+
1248+ var resLRs []* elbv2model.ListenerRule
1249+ assert .NoError (t , stack .ListResources (& resLRs ))
1250+
1251+ assert .Equal (t , len (tc .expectedRules ), len (resLRs ))
1252+
1253+ // cmp absolutely barfs trying to validate the TargetGroupARN due to stack id semantics
1254+ opt := cmp.Options {
1255+ cmpopts .IgnoreFields (elbv2model.TargetGroupTuple {}, "TargetGroupARN" ),
1256+ }
1257+
1258+ processedSet := make (map [* elbv2model.ListenerRule ]bool )
1259+ for _ , elr := range tc .expectedRules {
1260+ for _ , alr := range resLRs {
1261+ conditionsEqual := cmp .Equal (elr .Conditions , alr .Spec .Conditions )
1262+ actionsEqual := cmp .Equal (elr .Actions , alr .Spec .Actions , opt )
1263+ priorityEqual := elr .Priority == alr .Spec .Priority
1264+ fmt .Printf ("%+v,%+v,%+v\n " , conditionsEqual , actionsEqual , priorityEqual )
1265+ if conditionsEqual && actionsEqual && priorityEqual {
1266+ processedSet [alr ] = true
1267+ break
1268+ }
1269+ }
1270+ }
1271+
1272+ assert .Equal (t , len (tc .expectedRules ), len (processedSet ))
1273+
1274+ for _ , lr := range resLRs {
1275+ assert .Equal (t , tc .expectedTags , lr .Spec .Tags )
1276+ }
1277+ })
1278+ }
1279+ }
0 commit comments