Skip to content

Commit

Permalink
Merge branch 'main' into hash-utils
Browse files Browse the repository at this point in the history
  • Loading branch information
zhaohuabing authored Feb 23, 2024
2 parents e958010 + d407e0f commit 45b5ca3
Show file tree
Hide file tree
Showing 16 changed files with 992 additions and 2 deletions.
1 change: 1 addition & 0 deletions api/v1alpha1/retry_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type RetryOn struct {
Triggers []TriggerEnum `json:"triggers,omitempty"`

// HttpStatusCodes specifies the http status codes to be retried.
// The retriable-status-codes trigger must also be configured for these status codes to trigger a retry.
//
// +optional
HTTPStatusCodes []HTTPStatus `json:"httpStatusCodes,omitempty"`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,8 @@ spec:
properties:
httpStatusCodes:
description: HttpStatusCodes specifies the http status codes
to be retried.
to be retried. The retriable-status-codes trigger must also
be configured for these status codes to trigger a retry.
items:
description: HTTPStatus defines the http status code.
exclusiveMaximum: true
Expand Down
99 changes: 99 additions & 0 deletions internal/gatewayapi/backendtrafficpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen
fi *ir.FaultInjection
to *ir.Timeout
ka *ir.TCPKeepalive
rt *ir.Retry
)

// Build IR
Expand All @@ -274,6 +275,9 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen
if policy.Spec.TCPKeepalive != nil {
ka = t.buildTCPKeepAlive(policy)
}
if policy.Spec.Retry != nil {
rt = t.buildRetry(policy)
}
// Apply IR to all relevant routes
prefix := irRoutePrefix(route)
for _, ir := range xdsIR {
Expand All @@ -288,6 +292,7 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen
r.CircuitBreaker = cb
r.FaultInjection = fi
r.TCPKeepalive = ka
r.Retry = rt

// some timeout setting originate from the route
if policy.Spec.Timeout != nil {
Expand All @@ -311,6 +316,7 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back
fi *ir.FaultInjection
ct *ir.Timeout
ka *ir.TCPKeepalive
rt *ir.Retry
)

// Build IR
Expand All @@ -335,6 +341,9 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back
if policy.Spec.TCPKeepalive != nil {
ka = t.buildTCPKeepAlive(policy)
}
if policy.Spec.Retry != nil {
rt = t.buildRetry(policy)
}

// Apply IR to all the routes within the specific Gateway
// If the feature is already set, then skip it, since it must be have
Expand Down Expand Up @@ -367,6 +376,9 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back
if r.TCPKeepalive == nil {
r.TCPKeepalive = ka
}
if r.Retry == nil {
r.Retry = rt
}

if policy.Spec.Timeout != nil {
ct = t.buildTimeout(policy, r)
Expand Down Expand Up @@ -1014,3 +1026,90 @@ func (t *Translator) buildTCPKeepAlive(policy *egv1a1.BackendTrafficPolicy) *ir.
}
return ka
}

func (t *Translator) buildRetry(policy *egv1a1.BackendTrafficPolicy) *ir.Retry {
var rt *ir.Retry
if policy.Spec.Retry != nil {
prt := policy.Spec.Retry
rt = &ir.Retry{}

if prt.NumRetries != nil {
rt.NumRetries = ptr.To(uint32(*prt.NumRetries))
}

if prt.RetryOn != nil {
ro := &ir.RetryOn{}
bro := false
if prt.RetryOn.HTTPStatusCodes != nil {
ro.HTTPStatusCodes = makeIrStatusSet(prt.RetryOn.HTTPStatusCodes)
bro = true
}

if prt.RetryOn.Triggers != nil {
ro.Triggers = makeIrTriggerSet(prt.RetryOn.Triggers)
bro = true
}

if bro {
rt.RetryOn = ro
}
}

if prt.PerRetry != nil {
pr := &ir.PerRetryPolicy{}
bpr := false

if prt.PerRetry.Timeout != nil {
pr.Timeout = prt.PerRetry.Timeout
bpr = true
}

if prt.PerRetry.BackOff != nil {
if prt.PerRetry.BackOff.MaxInterval != nil || prt.PerRetry.BackOff.BaseInterval != nil {
bop := &ir.BackOffPolicy{}
if prt.PerRetry.BackOff.MaxInterval != nil {
bop.MaxInterval = prt.PerRetry.BackOff.MaxInterval
}

if prt.PerRetry.BackOff.BaseInterval != nil {
bop.BaseInterval = prt.PerRetry.BackOff.BaseInterval
}
pr.BackOff = bop
bpr = true
}
}

if bpr {
rt.PerRetry = pr
}
}
}

return rt
}

func makeIrStatusSet(in []egv1a1.HTTPStatus) []ir.HTTPStatus {
var irStatuses []ir.HTTPStatus
// deduplicate http statuses
statusSet := make(map[egv1a1.HTTPStatus]bool, len(in))
for _, r := range in {
if _, ok := statusSet[r]; !ok {
statusSet[r] = true
irStatuses = append(irStatuses, ir.HTTPStatus(r))
}
}
return irStatuses
}

func makeIrTriggerSet(in []egv1a1.TriggerEnum) []ir.TriggerEnum {
var irTriggers []ir.TriggerEnum
// deduplicate http statuses
triggerSet := make(map[egv1a1.TriggerEnum]bool, len(in))
for _, r := range in {
if _, ok := triggerSet[r]; !ok {
triggerSet[r] = true
irTriggers = append(irTriggers, ir.TriggerEnum(r))
}
}
return irTriggers
}
1 change: 1 addition & 0 deletions internal/gatewayapi/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,7 @@ func (t *Translator) processHTTPRouteParentRefListener(route RouteContext, route
Mirrors: routeRoute.Mirrors,
ExtensionRefs: routeRoute.ExtensionRefs,
Timeout: routeRoute.Timeout,
Retry: routeRoute.Retry,
}
// Don't bother copying over the weights unless the route has invalid backends.
if routeRoute.BackendWeights.Invalid > 0 {
Expand Down
110 changes: 110 additions & 0 deletions internal/gatewayapi/testdata/backendtrafficpolicy-with-retries.in.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
gateways:
- apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
namespace: envoy-gateway
name: gateway-1
spec:
gatewayClassName: envoy-gateway-class
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: All
- apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
namespace: envoy-gateway
name: gateway-2
spec:
gatewayClassName: envoy-gateway-class
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: All
grpcRoutes:
- apiVersion: gateway.networking.k8s.io/v1alpha2
kind: GRPCRoute
metadata:
namespace: default
name: grpcroute-1
spec:
parentRefs:
- namespace: envoy-gateway
name: gateway-1
sectionName: http
rules:
- backendRefs:
- name: service-1
port: 8080
httpRoutes:
- apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: default
name: httproute-1
spec:
hostnames:
- gateway.envoyproxy.io
parentRefs:
- namespace: envoy-gateway
name: gateway-2
sectionName: http
rules:
- matches:
- path:
value: "/"
backendRefs:
- name: service-1
port: 8080
backendTrafficPolicies:
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
namespace: envoy-gateway
name: policy-for-gateway
spec:
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: gateway-1
namespace: envoy-gateway
retry:
retryOn:
triggers:
- cancelled
perRetry:
timeout: 250ms
backoff:
baseInterval: 100ms
maxInterval: 10s
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
namespace: default
name: policy-for-route
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: httproute-1
namespace: default
retry:
numRetries: 5
retryOn:
httpStatusCodes:
- 429
- 503
triggers:
- connect-failure
- retriable-status-codes
perRetry:
timeout: 250ms
backoff:
baseInterval: 100ms
maxInterval: 10s
Loading

0 comments on commit 45b5ca3

Please sign in to comment.