diff --git a/pkg/apis/projectcontour/v1/httpproxy.go b/pkg/apis/projectcontour/v1/httpproxy.go index 59ad2e68..09ae6a2e 100644 --- a/pkg/apis/projectcontour/v1/httpproxy.go +++ b/pkg/apis/projectcontour/v1/httpproxy.go @@ -255,6 +255,10 @@ type TimeoutPolicy struct { Idle string `json:"idle,omitempty"` } +// RetryOn is a string type alias with validation to ensure that the value is valid. +// +kubebuilder:validation:Enum="5xx";gateway-error;reset;connect-failure;retriable-4xx;refused-stream;retriable-status-codes;retriable-headers;cancelled;deadline-exceeded;internal;resource-exhausted;unavailable +type RetryOn string + // RetryPolicy defines the attributes associated with retrying policy. type RetryPolicy struct { // NumRetries is maximum allowed number of retries. @@ -264,6 +268,28 @@ type RetryPolicy struct { // PerTryTimeout specifies the timeout per retry attempt. // Ignored if NumRetries is not supplied. PerTryTimeout string `json:"perTryTimeout,omitempty"` + // RetryOn specifies the conditions on which to retry a request. + // + // Supported [HTTP conditions](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter#x-envoy-retry-on): + // + // - `5xx` + // - `gateway-error` + // - `reset` + // - `connect-failure` + // - `retriable-4xx` + // - `refused-stream` + // - `retriable-status-codes` + // - `retriable-headers` + // + // Supported [gRPC conditions](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter#x-envoy-retry-grpc-on): + // + // - `cancelled` + // - `deadline-exceeded` + // - `internal` + // - `resource-exhausted` + // - `unavailable` + // +optional + RetryOn []RetryOn `json:"retryOn,omitempty"` } // ReplacePrefix describes a path prefix replacement. diff --git a/pkg/apis/projectcontour/v1/zz_generated.deepcopy.go b/pkg/apis/projectcontour/v1/zz_generated.deepcopy.go index be2d9f8d..9631d03d 100644 --- a/pkg/apis/projectcontour/v1/zz_generated.deepcopy.go +++ b/pkg/apis/projectcontour/v1/zz_generated.deepcopy.go @@ -300,6 +300,11 @@ func (in *ReplacePrefix) DeepCopy() *ReplacePrefix { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RetryPolicy) DeepCopyInto(out *RetryPolicy) { *out = *in + if in.RetryOn != nil { + in, out := &in.RetryOn, &out.RetryOn + *out = make([]RetryOn, len(*in)) + copy(*out, *in) + } return } @@ -338,7 +343,7 @@ func (in *Route) DeepCopyInto(out *Route) { if in.RetryPolicy != nil { in, out := &in.RetryPolicy, &out.RetryPolicy *out = new(RetryPolicy) - **out = **in + (*in).DeepCopyInto(*out) } if in.HealthCheckPolicy != nil { in, out := &in.HealthCheckPolicy, &out.HealthCheckPolicy diff --git a/pkg/router/contour.go b/pkg/router/contour.go index ef34ce08..27555932 100644 --- a/pkg/router/contour.go +++ b/pkg/router/contour.go @@ -19,6 +19,7 @@ package router import ( "context" "fmt" + "strings" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" @@ -444,11 +445,22 @@ func (cr *ContourRouter) makeRetryPolicy(canary *flaggerv1.Canary) *contourv1.Re return &contourv1.RetryPolicy{ NumRetries: uint32(canary.Spec.Service.Retries.Attempts), PerTryTimeout: canary.Spec.Service.Retries.PerTryTimeout, + RetryOn: makeRetryOn(canary.Spec.Service.Retries.RetryOn), } } return nil } +func makeRetryOn(retryOnString string) []contourv1.RetryOn { + retryOnSplit := strings.Split(retryOnString, ",") + + retryOn := make([]contourv1.RetryOn, len(retryOnSplit)) + for i, v := range retryOnSplit { + retryOn[i] = contourv1.RetryOn(v) + } + return retryOn +} + func (cr *ContourRouter) makeLinkerdHeaderValue(canary *flaggerv1.Canary, serviceName string) contourv1.HeaderValue { return contourv1.HeaderValue{ Name: "l5d-dst-override", diff --git a/pkg/router/router_test.go b/pkg/router/router_test.go index 917282bf..e077e008 100644 --- a/pkg/router/router_test.go +++ b/pkg/router/router_test.go @@ -132,6 +132,7 @@ func newTestCanary() *flaggerv1.Canary { Retries: &istiov1alpha3.HTTPRetry{ Attempts: 10, PerTryTimeout: "30s", + RetryOn: "connect-failure,gateway-error", }, Gateways: []string{ "public-gateway.istio", diff --git a/test/contour/test-custom.sh b/test/contour/test-custom.sh new file mode 100644 index 00000000..b58994b4 --- /dev/null +++ b/test/contour/test-custom.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash + +cat <