Skip to content

Commit 4f01595

Browse files
test: Correctly locate main route (non-managed one)
Signed-off-by: Kostis Kapelonis <kostis.kapelonis@octopus.com>
1 parent c4540eb commit 4f01595

1 file changed

Lines changed: 140 additions & 0 deletions

File tree

pkg/plugin/plugin_test.go

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,3 +1707,143 @@ func TestSetGRPCHeaderRouteTwoDistinctNamesAppendsBoth(t *testing.T) {
17071707
assert.Equal(t, "header-route-one", string(*rpcPluginImp.UpdatedGRPCRouteMock.Spec.Rules[1].Name))
17081708
assert.Equal(t, "header-route-two", string(*rpcPluginImp.UpdatedGRPCRouteMock.Spec.Rules[2].Name))
17091709
}
1710+
1711+
// TestGetRouteRuleOnlyReturnsRuleWithAllBackends verifies that getRouteRule only returns
1712+
// a route rule when ALL requested backends are present. This is a regression test for the
1713+
// bug where getRouteRule would return the first rule with any matching backend, even if
1714+
// not all backends were found.
1715+
//
1716+
// Bug scenario: When searching for a rule with both "canary" and "stable" backends,
1717+
// getRouteRule would incorrectly return a header route (which only has "canary" backend)
1718+
// if it appeared first in the rules list.
1719+
func TestGetRouteRuleOnlyReturnsRuleWithAllBackends(t *testing.T) {
1720+
// Create a route with two rules:
1721+
// 1. Header route with only canary backend (managed route)
1722+
// 2. Main route with both canary and stable backends
1723+
canaryName := gatewayv1.SectionName("header-route")
1724+
weight30 := int32(30)
1725+
weight70 := int32(70)
1726+
1727+
httpRoute := &gatewayv1.HTTPRoute{
1728+
ObjectMeta: metav1.ObjectMeta{
1729+
Name: "test-route",
1730+
Namespace: "default",
1731+
},
1732+
Spec: gatewayv1.HTTPRouteSpec{
1733+
Rules: []gatewayv1.HTTPRouteRule{
1734+
// Header route: only canary backend (this should NOT be returned)
1735+
{
1736+
Name: &canaryName,
1737+
Matches: []gatewayv1.HTTPRouteMatch{
1738+
{
1739+
Headers: []gatewayv1.HTTPHeaderMatch{
1740+
{
1741+
Name: "X-Canary",
1742+
Value: "true",
1743+
},
1744+
},
1745+
},
1746+
},
1747+
BackendRefs: []gatewayv1.HTTPBackendRef{
1748+
{
1749+
BackendRef: gatewayv1.BackendRef{
1750+
BackendObjectReference: gatewayv1.BackendObjectReference{
1751+
Name: "argo-rollouts-canary-service",
1752+
},
1753+
},
1754+
},
1755+
},
1756+
},
1757+
// Main route: both canary and stable backends (this SHOULD be returned)
1758+
{
1759+
BackendRefs: []gatewayv1.HTTPBackendRef{
1760+
{
1761+
BackendRef: gatewayv1.BackendRef{
1762+
BackendObjectReference: gatewayv1.BackendObjectReference{
1763+
Name: "argo-rollouts-stable-service",
1764+
},
1765+
Weight: &weight70,
1766+
},
1767+
},
1768+
{
1769+
BackendRef: gatewayv1.BackendRef{
1770+
BackendObjectReference: gatewayv1.BackendObjectReference{
1771+
Name: "argo-rollouts-canary-service",
1772+
},
1773+
Weight: &weight30,
1774+
},
1775+
},
1776+
},
1777+
},
1778+
},
1779+
},
1780+
}
1781+
1782+
httpRouteRuleList := HTTPRouteRuleList(httpRoute.Spec.Rules)
1783+
1784+
// Test: Search for rule with both backends
1785+
backendRefNameList := []string{"argo-rollouts-canary-service", "argo-rollouts-stable-service"}
1786+
httpRouteRule, err := getRouteRule(httpRouteRuleList, backendRefNameList...)
1787+
1788+
// Assert: Should find the main route (second rule), not the header route (first rule)
1789+
assert.NoError(t, err, "Should find a route with both backends")
1790+
assert.NotNil(t, httpRouteRule, "Route rule should not be nil")
1791+
assert.Equal(t, 2, len(httpRouteRule.BackendRefs), "Should return rule with 2 backends")
1792+
assert.Nil(t, httpRouteRule.Name, "Main route should not have a name (header routes have names)")
1793+
1794+
// Verify it's the correct rule by checking backend weights
1795+
var foundStable, foundCanary bool
1796+
for _, ref := range httpRouteRule.BackendRefs {
1797+
if ref.Name == "argo-rollouts-stable-service" {
1798+
foundStable = true
1799+
assert.Equal(t, int32(70), *ref.Weight)
1800+
}
1801+
if ref.Name == "argo-rollouts-canary-service" {
1802+
foundCanary = true
1803+
assert.Equal(t, int32(30), *ref.Weight)
1804+
}
1805+
}
1806+
assert.True(t, foundStable, "Should have stable backend")
1807+
assert.True(t, foundCanary, "Should have canary backend")
1808+
}
1809+
1810+
// TestGetRouteRuleReturnsErrorWhenBackendNotFound verifies that getRouteRule returns
1811+
// an error when no rule contains all requested backends.
1812+
func TestGetRouteRuleReturnsErrorWhenBackendNotFound(t *testing.T) {
1813+
// Create a route with only header routes (single backend each)
1814+
canaryName := gatewayv1.SectionName("header-route")
1815+
1816+
httpRoute := &gatewayv1.HTTPRoute{
1817+
ObjectMeta: metav1.ObjectMeta{
1818+
Name: "test-route",
1819+
Namespace: "default",
1820+
},
1821+
Spec: gatewayv1.HTTPRouteSpec{
1822+
Rules: []gatewayv1.HTTPRouteRule{
1823+
{
1824+
Name: &canaryName,
1825+
BackendRefs: []gatewayv1.HTTPBackendRef{
1826+
{
1827+
BackendRef: gatewayv1.BackendRef{
1828+
BackendObjectReference: gatewayv1.BackendObjectReference{
1829+
Name: "argo-rollouts-canary-service",
1830+
},
1831+
},
1832+
},
1833+
},
1834+
},
1835+
},
1836+
},
1837+
}
1838+
1839+
httpRouteRuleList := HTTPRouteRuleList(httpRoute.Spec.Rules)
1840+
1841+
// Test: Search for rule with both backends (only canary exists)
1842+
backendRefNameList := []string{"argo-rollouts-canary-service", "argo-rollouts-stable-service"}
1843+
httpRouteRule, err := getRouteRule(httpRouteRuleList, backendRefNameList...)
1844+
1845+
// Assert: Should return error because no rule has both backends
1846+
assert.Error(t, err, "Should return error when backend not found")
1847+
assert.Nil(t, httpRouteRule, "Route rule should be nil on error")
1848+
assert.Equal(t, BackendRefWasNotFoundInHTTPRouteError, err.Error())
1849+
}

0 commit comments

Comments
 (0)