Skip to content

Conversation

@ruslansuprun
Copy link
Contributor

Closes #135

Summary

  • Added support of TLSRoute

Changes

  • Added TLSRoute support for both: single route and list of routes
  • Updated mocks for new route type
  • Updated tests

Configuration example

trafficRouting:
  plugins:
    argoproj-labs/gatewayAPI:
      tlsRoute: tlsroute-basic
      namespace: default

Signed-off-by: Ruslan Suprun <ruslansuprun@gmail.com>
@ruslansuprun
Copy link
Contributor Author

@kostis-codefresh hey, is there anything i can do to make E2E Flaky tests pass?
Tried to make e2e-tests-flaky run locally, everything works fine

@kostis-codefresh
Copy link
Collaborator

Hey, many thanks for this.

No you are good. I have marked them flaky exactly for this reason. They pass locally but fail only in GitHub actions 😬

If you have tested everything locally, I will review soon.

@kostis-codefresh
Copy link
Collaborator

@CodiumAI-Agent /improve

@QodoAI-Agent
Copy link

QodoAI-Agent commented Sep 12, 2025

PR Code Suggestions ✨

Latest suggestions up to b6b532f

CategorySuggestion                                                                                                                                    Impact
Possible issue
Avoid nil dereference on error

Check the err before using updatedTLSRoute to avoid potential nil dereference when
update fails. Move test assignment after confirming no error.

pkg/plugin/tlsroute.go [47-55]

 updatedTLSRoute, err := tlsRouteClient.Update(ctx, tlsRoute, metav1.UpdateOptions{})
-if r.IsTest {
-	r.UpdatedTLSRouteMock = updatedTLSRoute
-}
 if err != nil {
 	return pluginTypes.RpcError{
 		ErrorString: err.Error(),
 	}
 }
+if r.IsTest {
+	r.UpdatedTLSRouteMock = updatedTLSRoute
+}
Suggestion importance[1-10]: 7

__

Why: Moving the test assignment after the error check avoids using a potentially invalid result; it’s a sound defensive fix with clear correspondence to the code.

Medium
Clamp weight into valid range

Guard against out-of-range desiredWeight values to prevent negative or >100 weights,
which can break routing. Clamp the value to [0,100] before applying to BackendRefs.

pkg/plugin/tlsroute.go [34-46]

+// clamp desiredWeight into [0,100]
+if desiredWeight < 0 {
+	desiredWeight = 0
+} else if desiredWeight > 100 {
+	desiredWeight = 100
+}
 for _, ref := range canaryBackendRefs {
 	ref.Weight = &desiredWeight
 }
-...
 restWeight := 100 - desiredWeight
 for _, ref := range stableBackendRefs {
 	ref.Weight = &restWeight
 }
Suggestion importance[1-10]: 6

__

Why: Clamping desiredWeight to [0,100] prevents invalid weights and aligns with assumed semantics; the mapping to the code region is correct, and the change is low-risk but beneficial.

Low
General
Avoid shared config mutation

Avoid mutating shared gatewayAPIConfig while iterating multiple routes, which can
cause race or cross-route contamination. Pass a shallow copy with TLSRoute set per
iteration.

pkg/plugin/plugin.go [104-108]

 r.LogCtx.Info(fmt.Sprintf("[SetWeight] plugin %q controls TLSRoutes: %v", PluginName, getGatewayAPIRouteNameList(gatewayAPIConfig.TLSRoutes)))
 rpcError = forEachGatewayAPIRoute(gatewayAPIConfig.TLSRoutes, func(route TLSRoute) pluginTypes.RpcError {
-	gatewayAPIConfig.TLSRoute = route.Name
-	return r.setTLSRouteWeight(rollout, desiredWeight, gatewayAPIConfig)
+	cfg := *gatewayAPIConfig
+	cfg.TLSRoute = route.Name
+	return r.setTLSRouteWeight(rollout, desiredWeight, &cfg)
 })
Suggestion importance[1-10]: 7

__

Why: Copying the config per iteration avoids unintended side effects when iterating multiple routes; it improves safety and maintainability without altering behavior.

Medium

Previous suggestions

Suggestions up to commit b6b532f
CategorySuggestion                                                                                                                                    Impact
Possible issue
Handle update error before use

Check and handle the error from Update before using updatedTLSRoute. As written,
updatedTLSRoute may be nil on error, leading to a potential nil dereference when
assigning to r.UpdatedTLSRouteMock.

pkg/plugin/tlsroute.go [47-55]

 updatedTLSRoute, err := tlsRouteClient.Update(ctx, tlsRoute, metav1.UpdateOptions{})
-if r.IsTest {
-	r.UpdatedTLSRouteMock = updatedTLSRoute
-}
 if err != nil {
 	return pluginTypes.RpcError{
 		ErrorString: err.Error(),
 	}
 }
+if r.IsTest {
+	r.UpdatedTLSRouteMock = updatedTLSRoute
+}
Suggestion importance[1-10]: 8

__

Why: Correctly reorders error handling for Update to avoid using a potentially nil updatedTLSRoute, preventing a possible nil dereference in tests; it's accurate and improves robustness.

Medium
General
Clamp weight to valid range

Guard against invalid desiredWeight values that can cause negative or >100 weights.
Clamp the desired weight to [0,100] to prevent underflow or invalid percentages
impacting routing behavior.

pkg/plugin/tlsroute.go [34-46]

+// clamp desiredWeight to [0, 100]
+if desiredWeight < 0 {
+	desiredWeight = 0
+} else if desiredWeight > 100 {
+	desiredWeight = 100
+}
 for _, ref := range canaryBackendRefs {
 	ref.Weight = &desiredWeight
 }
-...
 restWeight := 100 - desiredWeight
 for _, ref := range stableBackendRefs {
 	ref.Weight = &restWeight
 }
Suggestion importance[1-10]: 7

__

Why: Adds validation to prevent invalid weights (<0 or >100) that could cause incorrect routing; not strictly required by the PR but a sensible safety improvement.

Medium
Default namespace for discovery

Ensure gatewayAPIConfig.Namespace is set before selector-based discovery for
TLSRoutes. If absent, discovery calls may default to an empty namespace, causing
failed lookups.

pkg/plugin/plugin.go [214-221]

 if gatewayAPIConfig.HTTPRouteSelector != nil ||
 	gatewayAPIConfig.GRPCRouteSelector != nil ||
 	gatewayAPIConfig.TCPRouteSelector != nil ||
 	gatewayAPIConfig.TLSRouteSelector != nil {
+	// default namespace from rollout if not provided
+	if gatewayAPIConfig.Namespace == "" {
+		gatewayAPIConfig.Namespace = rollout.Namespace
+	}
 	if err := r.discoverRoutesBySelector(rollout, gatewayAPIConfig); err != nil {
 		return nil, err
 	}
 }
Suggestion importance[1-10]: 6

__

Why: Setting a default namespace from the rollout before discovery can prevent empty-namespace lookups; useful but somewhat contextual since other parts may already set namespace.

Low
Suggestions up to commit b6b532f
CategorySuggestion                                                                                                                                    Impact
General
Prevent shared state mutation

Avoid mutating gatewayAPIConfig.TLSRoute inside the loop, which can leak state
across iterations and later calls. Pass the route name to setTLSRouteWeight via a
shallow copy of the config.

pkg/plugin/plugin.go [104-108]

 r.LogCtx.Info(fmt.Sprintf("[SetWeight] plugin %q controls TLSRoutes: %v", PluginName, getGatewayAPIRouteNameList(gatewayAPIConfig.TLSRoutes)))
 rpcError = forEachGatewayAPIRoute(gatewayAPIConfig.TLSRoutes, func(route TLSRoute) pluginTypes.RpcError {
-	gatewayAPIConfig.TLSRoute = route.Name
-	return r.setTLSRouteWeight(rollout, desiredWeight, gatewayAPIConfig)
+	cfgCopy := *gatewayAPIConfig
+	cfgCopy.TLSRoute = route.Name
+	return r.setTLSRouteWeight(rollout, desiredWeight, &cfgCopy)
 })
Suggestion importance[1-10]: 8

__

Why: Avoids mutating shared gatewayAPIConfig inside iteration by copying before setting TLSRoute, reducing side effects and potential bugs across route processing.

Medium
Possible issue
Handle update error before assignment

Check and handle the error from Update before using updatedTLSRoute. Using
updatedTLSRoute when err is non-nil risks propagating a nil or stale object into
r.UpdatedTLSRouteMock.

pkg/plugin/tlsroute.go [47-55]

 updatedTLSRoute, err := tlsRouteClient.Update(ctx, tlsRoute, metav1.UpdateOptions{})
-if r.IsTest {
-	r.UpdatedTLSRouteMock = updatedTLSRoute
-}
 if err != nil {
 	return pluginTypes.RpcError{
 		ErrorString: err.Error(),
 	}
 }
+if r.IsTest {
+	r.UpdatedTLSRouteMock = updatedTLSRoute
+}
Suggestion importance[1-10]: 7

__

Why: Corrects error-handling order to avoid assigning updatedTLSRoute when err is non-nil, preventing test-state corruption; a modest but sound reliability improvement aligned with the new code.

Medium
Validate desired weight bounds

Guard against desiredWeight values outside 0-100 to prevent negative restWeight or
overflow. Return a clear error if the desired weight is invalid.

pkg/plugin/tlsroute.go [43-46]

+if desiredWeight < 0 || desiredWeight > 100 {
+	return pluginTypes.RpcError{ErrorString: "desiredWeight must be between 0 and 100"}
+}
 restWeight := 100 - desiredWeight
 for _, ref := range stableBackendRefs {
 	ref.Weight = &restWeight
 }
Suggestion importance[1-10]: 6

__

Why: Adds input validation to avoid negative restWeight and invalid states; beneficial but not critical since callers typically supply valid weights.

Low

@kostis-codefresh kostis-codefresh merged commit 864a46d into argoproj-labs:main Sep 12, 2025
6 of 7 checks passed
@kostis-codefresh
Copy link
Collaborator

This is now part of 0.8.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support of TLSRoute to plugin

3 participants