Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(translator): implement timeout in ClientTrafficPolicy #2667

Merged
merged 10 commits into from
Feb 22, 2024
34 changes: 34 additions & 0 deletions internal/gatewayapi/clienttrafficpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,11 @@ func (t *Translator) translateClientTrafficPolicyForListener(policy *egv1a1.Clie
// Translate Path Settings
translatePathSettings(policy.Spec.Path, httpIR)

// Translate Client Timeout Settings
if err := translateClientTimeout(policy.Spec.Timeout, httpIR); err != nil {
return err
}

// Translate HTTP1 Settings
if err := translateHTTP1Settings(policy.Spec.HTTP1, httpIR); err != nil {
return err
Expand Down Expand Up @@ -395,6 +400,35 @@ func translatePathSettings(pathSettings *egv1a1.PathSettings, httpIR *ir.HTTPLis
}
}

func translateClientTimeout(clientTimeout *egv1a1.ClientTimeout, httpIR *ir.HTTPListener) error {
if clientTimeout == nil {
return nil
}

if clientTimeout.HTTP != nil {
if clientTimeout.HTTP.RequestReceivedTimeout != nil {
d, err := time.ParseDuration(string(*clientTimeout.HTTP.RequestReceivedTimeout))
if err != nil {
return err
}
switch {
case httpIR.Timeout == nil:
httpIR.Timeout = &ir.ClientTimeout{}
fallthrough

case httpIR.Timeout.HTTP == nil:
httpIR.Timeout.HTTP = &ir.HTTPClientTimeout{}
}

httpIR.Timeout.HTTP.RequestReceivedTimeout = &metav1.Duration{
Duration: d,
}
}
}

return nil
}

func translateListenerProxyProtocol(enableProxyProtocol *bool, httpIR *ir.HTTPListener) {
// Return early if not set
if enableProxyProtocol == nil {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
clientTrafficPolicies:
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: ClientTrafficPolicy
metadata:
namespace: envoy-gateway
name: target-gateway
spec:
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: gateway
namespace: envoy-gateway
timeout:
http:
requestReceivedTimeout: "5sec"
gateways:
- apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
namespace: envoy-gateway
name: gateway
spec:
gatewayClassName: envoy-gateway-class
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: Same

Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
clientTrafficPolicies:
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: ClientTrafficPolicy
metadata:
creationTimestamp: null
name: target-gateway
namespace: envoy-gateway
spec:
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: gateway
namespace: envoy-gateway
timeout:
http:
requestReceivedTimeout: 5sec
status:
conditions:
- lastTransitionTime: null
message: 'Time: unknown unit "sec" in duration "5sec"'
reason: Invalid
status: "False"
type: Accepted
gateways:
- apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
creationTimestamp: null
name: gateway
namespace: envoy-gateway
spec:
gatewayClassName: envoy-gateway-class
listeners:
- allowedRoutes:
namespaces:
from: Same
name: http
port: 80
protocol: HTTP
status:
listeners:
- attachedRoutes: 0
conditions:
- lastTransitionTime: null
message: Sending translated listener configuration to the data plane
reason: Programmed
status: "True"
type: Programmed
- lastTransitionTime: null
message: Listener has been successfully translated
reason: Accepted
status: "True"
type: Accepted
- lastTransitionTime: null
message: Listener references have been resolved
reason: ResolvedRefs
status: "True"
type: ResolvedRefs
name: http
supportedKinds:
- group: gateway.networking.k8s.io
kind: HTTPRoute
- group: gateway.networking.k8s.io
kind: GRPCRoute
infraIR:
envoy-gateway/gateway:
proxy:
listeners:
- address: null
name: envoy-gateway/gateway/http
ports:
- containerPort: 10080
name: http
protocol: HTTP
servicePort: 80
metadata:
labels:
gateway.envoyproxy.io/owning-gateway-name: gateway
gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway
name: envoy-gateway/gateway
xdsIR:
envoy-gateway/gateway:
accessLog:
text:
- path: /dev/stdout
http:
- address: 0.0.0.0
hostnames:
- '*'
isHTTP2: false
name: envoy-gateway/gateway/http
path:
escapedSlashesAction: UnescapeAndRedirect
mergeSlashes: true
port: 10080
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
clientTrafficPolicies:
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: ClientTrafficPolicy
metadata:
namespace: envoy-gateway
name: target-gateway
spec:
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: gateway
namespace: envoy-gateway
sectionName: http-1
timeout:
http:
requestReceivedTimeout: "5s"
gateways:
- apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
namespace: envoy-gateway
name: gateway
spec:
gatewayClassName: envoy-gateway-class
listeners:
- name: http-1
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: Same
- name: http-2
protocol: HTTP
port: 8080
allowedRoutes:
namespaces:
from: Same

144 changes: 144 additions & 0 deletions internal/gatewayapi/testdata/clienttrafficpolicy-timeout.out.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
clientTrafficPolicies:
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: ClientTrafficPolicy
metadata:
creationTimestamp: null
name: target-gateway
namespace: envoy-gateway
spec:
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: gateway
namespace: envoy-gateway
sectionName: http-1
timeout:
http:
requestReceivedTimeout: 5s
status:
conditions:
- lastTransitionTime: null
message: ClientTrafficPolicy has been accepted.
reason: Accepted
status: "True"
type: Accepted
gateways:
- apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
creationTimestamp: null
name: gateway
namespace: envoy-gateway
spec:
gatewayClassName: envoy-gateway-class
listeners:
- allowedRoutes:
namespaces:
from: Same
name: http-1
port: 80
protocol: HTTP
- allowedRoutes:
namespaces:
from: Same
name: http-2
port: 8080
protocol: HTTP
status:
listeners:
- attachedRoutes: 0
conditions:
- lastTransitionTime: null
message: Sending translated listener configuration to the data plane
reason: Programmed
status: "True"
type: Programmed
- lastTransitionTime: null
message: Listener has been successfully translated
reason: Accepted
status: "True"
type: Accepted
- lastTransitionTime: null
message: Listener references have been resolved
reason: ResolvedRefs
status: "True"
type: ResolvedRefs
name: http-1
supportedKinds:
- group: gateway.networking.k8s.io
kind: HTTPRoute
- group: gateway.networking.k8s.io
kind: GRPCRoute
- attachedRoutes: 0
conditions:
- lastTransitionTime: null
message: Sending translated listener configuration to the data plane
reason: Programmed
status: "True"
type: Programmed
- lastTransitionTime: null
message: Listener has been successfully translated
reason: Accepted
status: "True"
type: Accepted
- lastTransitionTime: null
message: Listener references have been resolved
reason: ResolvedRefs
status: "True"
type: ResolvedRefs
name: http-2
supportedKinds:
- group: gateway.networking.k8s.io
kind: HTTPRoute
- group: gateway.networking.k8s.io
kind: GRPCRoute
infraIR:
envoy-gateway/gateway:
proxy:
listeners:
- address: null
name: envoy-gateway/gateway/http-1
ports:
- containerPort: 10080
name: http-1
protocol: HTTP
servicePort: 80
- address: null
name: envoy-gateway/gateway/http-2
ports:
- containerPort: 8080
name: http-2
protocol: HTTP
servicePort: 8080
metadata:
labels:
gateway.envoyproxy.io/owning-gateway-name: gateway
gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway
name: envoy-gateway/gateway
xdsIR:
envoy-gateway/gateway:
accessLog:
text:
- path: /dev/stdout
http:
- address: 0.0.0.0
hostnames:
- '*'
isHTTP2: false
name: envoy-gateway/gateway/http-1
path:
escapedSlashesAction: UnescapeAndRedirect
mergeSlashes: true
port: 10080
timeout:
http:
requestReceivedTimeout: 5s
- address: 0.0.0.0
hostnames:
- '*'
isHTTP2: false
name: envoy-gateway/gateway/http-2
path:
escapedSlashesAction: UnescapeAndRedirect
mergeSlashes: true
port: 8080
17 changes: 17 additions & 0 deletions internal/ir/xds.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ type HTTPListener struct {
// HTTP1 provides HTTP/1 configuration on the listener
// +optional
HTTP1 *HTTP1Settings `json:"http1,omitempty" yaml:"http1,omitempty"`
// ClientTimeout sets the timeout configuration for downstream connections
Timeout *ClientTimeout `json:"timeout,omitempty" yaml:"clientTimeout,omitempty"`
}

// Validate the fields within the HTTPListener structure
Expand Down Expand Up @@ -389,6 +391,21 @@ type HeaderSettings struct {
EnableEnvoyHeaders bool `json:"enableEnvoyHeaders,omitempty" yaml:"enableEnvoyHeaders,omitempty"`
}

// ClientTimeout sets the timeout configuration for downstream connections
// +k8s:deepcopy-gen=true
type ClientTimeout struct {
// Timeout settings for HTTP.
HTTP *HTTPClientTimeout `json:"http,omitempty" yaml:"http,omitempty"`
}

// HTTPClientTimeout set the configuration for client HTTP.
// +k8s:deepcopy-gen=true
type HTTPClientTimeout struct {
// The duration envoy waits for the complete request reception. This timer starts upon request
// initiation and stops when either the last byte of the request is sent upstream or when the response begins.
RequestReceivedTimeout *metav1.Duration `json:"requestReceivedTimeout,omitempty" yaml:"requestReceivedTimeout,omitempty"`
}

// HTTPRoute holds the route information associated with the HTTP Route
// +k8s:deepcopy-gen=true
type HTTPRoute struct {
Expand Down
Loading