@@ -2,6 +2,7 @@ package ingress
22
33import (
44 "context"
5+ "sort"
56 "testing"
67
78 awssdk "github.com/aws/aws-sdk-go-v2/aws"
@@ -1347,3 +1348,358 @@ func Test_defaultModelBuildTask_buildFrontendNlbListeners(t *testing.T) {
13471348 })
13481349 }
13491350}
1351+
1352+ func Test_defaultModelBuildTask_getFrontendNlbAttributes (t * testing.T ) {
1353+ tests := []struct {
1354+ name string
1355+ ingGroup Group
1356+ wantAttributes map [string ]string
1357+ wantErr bool
1358+ expectedErrMsg string
1359+ }{
1360+ {
1361+ name : "no attributes specified" ,
1362+ ingGroup : Group {
1363+ Members : []ClassifiedIngress {
1364+ {
1365+ Ing : & networking.Ingress {
1366+ ObjectMeta : metav1.ObjectMeta {
1367+ Name : "ingress1" ,
1368+ Namespace : "default" ,
1369+ },
1370+ },
1371+ },
1372+ },
1373+ },
1374+ wantAttributes : nil ,
1375+ wantErr : false ,
1376+ },
1377+ {
1378+ name : "valid DNS client routing policy - availability_zone_affinity" ,
1379+ ingGroup : Group {
1380+ Members : []ClassifiedIngress {
1381+ {
1382+ Ing : & networking.Ingress {
1383+ ObjectMeta : metav1.ObjectMeta {
1384+ Name : "ingress1" ,
1385+ Namespace : "default" ,
1386+ Annotations : map [string ]string {
1387+ "alb.ingress.kubernetes.io/aws-load-balancer-attributes" : "dns_record.client_routing_policy=availability_zone_affinity" ,
1388+ },
1389+ },
1390+ },
1391+ },
1392+ },
1393+ },
1394+ wantAttributes : map [string ]string {
1395+ "dns_record.client_routing_policy" : "availability_zone_affinity" ,
1396+ },
1397+ wantErr : false ,
1398+ },
1399+ {
1400+ name : "valid DNS client routing policy - partial_availability_zone_affinity" ,
1401+ ingGroup : Group {
1402+ Members : []ClassifiedIngress {
1403+ {
1404+ Ing : & networking.Ingress {
1405+ ObjectMeta : metav1.ObjectMeta {
1406+ Name : "ingress1" ,
1407+ Namespace : "default" ,
1408+ Annotations : map [string ]string {
1409+ "alb.ingress.kubernetes.io/aws-load-balancer-attributes" : "dns_record.client_routing_policy=partial_availability_zone_affinity" ,
1410+ },
1411+ },
1412+ },
1413+ },
1414+ },
1415+ },
1416+ wantAttributes : map [string ]string {
1417+ "dns_record.client_routing_policy" : "partial_availability_zone_affinity" ,
1418+ },
1419+ wantErr : false ,
1420+ },
1421+ {
1422+ name : "valid DNS client routing policy - any_availability_zone" ,
1423+ ingGroup : Group {
1424+ Members : []ClassifiedIngress {
1425+ {
1426+ Ing : & networking.Ingress {
1427+ ObjectMeta : metav1.ObjectMeta {
1428+ Name : "ingress1" ,
1429+ Namespace : "default" ,
1430+ Annotations : map [string ]string {
1431+ "alb.ingress.kubernetes.io/aws-load-balancer-attributes" : "dns_record.client_routing_policy=any_availability_zone" ,
1432+ },
1433+ },
1434+ },
1435+ },
1436+ },
1437+ },
1438+ wantAttributes : map [string ]string {
1439+ "dns_record.client_routing_policy" : "any_availability_zone" ,
1440+ },
1441+ wantErr : false ,
1442+ },
1443+ {
1444+ name : "invalid DNS client routing policy" ,
1445+ ingGroup : Group {
1446+ Members : []ClassifiedIngress {
1447+ {
1448+ Ing : & networking.Ingress {
1449+ ObjectMeta : metav1.ObjectMeta {
1450+ Name : "ingress1" ,
1451+ Namespace : "default" ,
1452+ Annotations : map [string ]string {
1453+ "alb.ingress.kubernetes.io/aws-load-balancer-attributes" : "dns_record.client_routing_policy=invalid_policy" ,
1454+ },
1455+ },
1456+ },
1457+ },
1458+ },
1459+ },
1460+ wantAttributes : nil ,
1461+ wantErr : true ,
1462+ expectedErrMsg : "invalid dns_record.client_routing_policy set in annotation" ,
1463+ },
1464+ {
1465+ name : "multiple attributes with valid DNS policy" ,
1466+ ingGroup : Group {
1467+ Members : []ClassifiedIngress {
1468+ {
1469+ Ing : & networking.Ingress {
1470+ ObjectMeta : metav1.ObjectMeta {
1471+ Name : "ingress1" ,
1472+ Namespace : "default" ,
1473+ Annotations : map [string ]string {
1474+ "alb.ingress.kubernetes.io/aws-load-balancer-attributes" : "dns_record.client_routing_policy=availability_zone_affinity,cross_zone.enabled=true" ,
1475+ },
1476+ },
1477+ },
1478+ },
1479+ },
1480+ },
1481+ wantAttributes : map [string ]string {
1482+ "dns_record.client_routing_policy" : "availability_zone_affinity" ,
1483+ "cross_zone.enabled" : "true" ,
1484+ },
1485+ wantErr : false ,
1486+ },
1487+ {
1488+ name : "consistent attributes across multiple ingresses" ,
1489+ ingGroup : Group {
1490+ Members : []ClassifiedIngress {
1491+ {
1492+ Ing : & networking.Ingress {
1493+ ObjectMeta : metav1.ObjectMeta {
1494+ Name : "ingress1" ,
1495+ Namespace : "default" ,
1496+ Annotations : map [string ]string {
1497+ "alb.ingress.kubernetes.io/aws-load-balancer-attributes" : "dns_record.client_routing_policy=availability_zone_affinity" ,
1498+ },
1499+ },
1500+ },
1501+ },
1502+ {
1503+ Ing : & networking.Ingress {
1504+ ObjectMeta : metav1.ObjectMeta {
1505+ Name : "ingress2" ,
1506+ Namespace : "default" ,
1507+ Annotations : map [string ]string {
1508+ "alb.ingress.kubernetes.io/aws-load-balancer-attributes" : "dns_record.client_routing_policy=availability_zone_affinity" ,
1509+ },
1510+ },
1511+ },
1512+ },
1513+ },
1514+ },
1515+ wantAttributes : map [string ]string {
1516+ "dns_record.client_routing_policy" : "availability_zone_affinity" ,
1517+ },
1518+ wantErr : false ,
1519+ },
1520+ {
1521+ name : "conflicting attributes across multiple ingresses" ,
1522+ ingGroup : Group {
1523+ Members : []ClassifiedIngress {
1524+ {
1525+ Ing : & networking.Ingress {
1526+ ObjectMeta : metav1.ObjectMeta {
1527+ Name : "ingress1" ,
1528+ Namespace : "default" ,
1529+ Annotations : map [string ]string {
1530+ "alb.ingress.kubernetes.io/aws-load-balancer-attributes" : "dns_record.client_routing_policy=availability_zone_affinity" ,
1531+ },
1532+ },
1533+ },
1534+ },
1535+ {
1536+ Ing : & networking.Ingress {
1537+ ObjectMeta : metav1.ObjectMeta {
1538+ Name : "ingress2" ,
1539+ Namespace : "default" ,
1540+ Annotations : map [string ]string {
1541+ "alb.ingress.kubernetes.io/aws-load-balancer-attributes" : "dns_record.client_routing_policy=any_availability_zone" ,
1542+ },
1543+ },
1544+ },
1545+ },
1546+ },
1547+ },
1548+ wantAttributes : nil ,
1549+ wantErr : true ,
1550+ expectedErrMsg : "conflicting frontend NLB attributes" ,
1551+ },
1552+ {
1553+ name : "mixed ingresses - some with attributes, some without" ,
1554+ ingGroup : Group {
1555+ Members : []ClassifiedIngress {
1556+ {
1557+ Ing : & networking.Ingress {
1558+ ObjectMeta : metav1.ObjectMeta {
1559+ Name : "ingress1" ,
1560+ Namespace : "default" ,
1561+ Annotations : map [string ]string {
1562+ "alb.ingress.kubernetes.io/aws-load-balancer-attributes" : "dns_record.client_routing_policy=availability_zone_affinity" ,
1563+ },
1564+ },
1565+ },
1566+ },
1567+ {
1568+ Ing : & networking.Ingress {
1569+ ObjectMeta : metav1.ObjectMeta {
1570+ Name : "ingress2" ,
1571+ Namespace : "default" ,
1572+ },
1573+ },
1574+ },
1575+ },
1576+ },
1577+ wantAttributes : nil ,
1578+ wantErr : true ,
1579+ expectedErrMsg : "conflicting frontend NLB attributes" ,
1580+ },
1581+ }
1582+
1583+ for _ , tt := range tests {
1584+ t .Run (tt .name , func (t * testing.T ) {
1585+ parser := annotations .NewSuffixAnnotationParser ("alb.ingress.kubernetes.io" )
1586+ task := & defaultModelBuildTask {
1587+ annotationParser : parser ,
1588+ ingGroup : tt .ingGroup ,
1589+ }
1590+
1591+ gotAttributes , err := task .getFrontendNlbAttributes ()
1592+
1593+ if tt .wantErr {
1594+ assert .Error (t , err )
1595+ if tt .expectedErrMsg != "" {
1596+ assert .Contains (t , err .Error (), tt .expectedErrMsg )
1597+ }
1598+ } else {
1599+ assert .NoError (t , err )
1600+ assert .Equal (t , tt .wantAttributes , gotAttributes )
1601+ }
1602+ })
1603+ }
1604+ }
1605+
1606+ func Test_defaultModelBuildTask_buildFrontendNlbAttributes (t * testing.T ) {
1607+ tests := []struct {
1608+ name string
1609+ ingGroup Group
1610+ wantAttributes []elbv2model.LoadBalancerAttribute
1611+ wantErr bool
1612+ expectedErrMsg string
1613+ }{
1614+ {
1615+ name : "no attributes specified" ,
1616+ ingGroup : Group {
1617+ Members : []ClassifiedIngress {
1618+ {
1619+ Ing : & networking.Ingress {
1620+ ObjectMeta : metav1.ObjectMeta {
1621+ Name : "ingress1" ,
1622+ Namespace : "default" ,
1623+ },
1624+ },
1625+ },
1626+ },
1627+ },
1628+ wantAttributes : []elbv2model.LoadBalancerAttribute {},
1629+ wantErr : false ,
1630+ },
1631+ {
1632+ name : "valid attributes conversion" ,
1633+ ingGroup : Group {
1634+ Members : []ClassifiedIngress {
1635+ {
1636+ Ing : & networking.Ingress {
1637+ ObjectMeta : metav1.ObjectMeta {
1638+ Name : "ingress1" ,
1639+ Namespace : "default" ,
1640+ Annotations : map [string ]string {
1641+ "alb.ingress.kubernetes.io/aws-load-balancer-attributes" : "dns_record.client_routing_policy=availability_zone_affinity,cross_zone.enabled=true" ,
1642+ },
1643+ },
1644+ },
1645+ },
1646+ },
1647+ },
1648+ wantAttributes : []elbv2model.LoadBalancerAttribute {
1649+ {Key : "cross_zone.enabled" , Value : "true" },
1650+ {Key : "dns_record.client_routing_policy" , Value : "availability_zone_affinity" },
1651+ },
1652+ wantErr : false ,
1653+ },
1654+ {
1655+ name : "invalid DNS policy should cause error" ,
1656+ ingGroup : Group {
1657+ Members : []ClassifiedIngress {
1658+ {
1659+ Ing : & networking.Ingress {
1660+ ObjectMeta : metav1.ObjectMeta {
1661+ Name : "ingress1" ,
1662+ Namespace : "default" ,
1663+ Annotations : map [string ]string {
1664+ "alb.ingress.kubernetes.io/aws-load-balancer-attributes" : "dns_record.client_routing_policy=invalid_policy" ,
1665+ },
1666+ },
1667+ },
1668+ },
1669+ },
1670+ },
1671+ wantAttributes : []elbv2model.LoadBalancerAttribute {},
1672+ wantErr : true ,
1673+ expectedErrMsg : "invalid dns_record.client_routing_policy set in annotation" ,
1674+ },
1675+ }
1676+
1677+ for _ , tt := range tests {
1678+ t .Run (tt .name , func (t * testing.T ) {
1679+ parser := annotations .NewSuffixAnnotationParser ("alb.ingress.kubernetes.io" )
1680+ task := & defaultModelBuildTask {
1681+ annotationParser : parser ,
1682+ ingGroup : tt .ingGroup ,
1683+ }
1684+
1685+ gotAttributes , err := task .buildFrontendNlbAttributes ()
1686+
1687+ if tt .wantErr {
1688+ assert .Error (t , err )
1689+ if tt .expectedErrMsg != "" {
1690+ assert .Contains (t , err .Error (), tt .expectedErrMsg )
1691+ }
1692+ } else {
1693+ assert .NoError (t , err )
1694+ // Sort both slices to ensure stable comparison
1695+ sort .Slice (gotAttributes , func (i , j int ) bool {
1696+ return gotAttributes [i ].Key < gotAttributes [j ].Key
1697+ })
1698+ sort .Slice (tt .wantAttributes , func (i , j int ) bool {
1699+ return tt .wantAttributes [i ].Key < tt .wantAttributes [j ].Key
1700+ })
1701+ assert .Equal (t , tt .wantAttributes , gotAttributes )
1702+ }
1703+ })
1704+ }
1705+ }
0 commit comments