diff --git a/api/v1alpha1/backendtrafficpolicy_types.go b/api/v1alpha1/backendtrafficpolicy_types.go index 967985426b..63ae9b5d5a 100644 --- a/api/v1alpha1/backendtrafficpolicy_types.go +++ b/api/v1alpha1/backendtrafficpolicy_types.go @@ -126,6 +126,24 @@ type BackendTelemetry struct { // // +optional Tracing *Tracing `json:"tracing,omitempty"` + // Metrics defines metrics configuration for the backend or Route. + // + // +optional + Metrics *BackendMetrics `json:"metrics,omitempty"` +} + +type BackendMetrics struct { + // RouteStatName defines the value of the Route stat_prefix, determining how the route stats are named. + // For more details, see envoy docs: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#config-route-v3-route + // The supported operators for this pattern are: + // %ROUTE_NAME%: name of Gateway API xRoute resource + // %ROUTE_NAMESPACE%: namespace of Gateway API xRoute resource + // %ROUTE_KIND%: kind of Gateway API xRoute resource + // Example: %ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME% => httproute/my-ns/my-route + // Disabled by default. + // + // +optional + RouteStatName *string `json:"routeStatName,omitempty"` } // ProtocolUpgradeConfig specifies the configuration for protocol upgrades. diff --git a/api/v1alpha1/validation/envoyproxy_validate.go b/api/v1alpha1/validation/envoyproxy_validate.go index 66230e4bda..6715a050a0 100644 --- a/api/v1alpha1/validation/envoyproxy_validate.go +++ b/api/v1alpha1/validation/envoyproxy_validate.go @@ -19,6 +19,8 @@ import ( egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" ) +var statNameRegex = regexp.MustCompile("%[^%]*%") + // ValidateEnvoyProxy validates the provided EnvoyProxy. func ValidateEnvoyProxy(proxy *egv1a1.EnvoyProxy) error { var errs []error @@ -213,8 +215,8 @@ func validateProxyTelemetry(spec *egv1a1.EnvoyProxySpec) []error { } if spec.Telemetry.Metrics.ClusterStatName != nil { - if clusterStatErrs := validateClusterStatName(*spec.Telemetry.Metrics.ClusterStatName); clusterStatErrs != nil { - errs = append(errs, clusterStatErrs...) + if clusterStatErr := ValidateClusterStatName(*spec.Telemetry.Metrics.ClusterStatName); clusterStatErr != nil { + errs = append(errs, clusterStatErr) } } } @@ -294,7 +296,22 @@ func validateFilterOrder(filterOrder []egv1a1.FilterPosition) error { return nil } -func validateClusterStatName(clusterStatName string) []error { +func ValidateRouteStatName(routeStatName string) error { + supportedOperators := map[string]bool{ + egv1a1.StatFormatterRouteName: true, + egv1a1.StatFormatterRouteNamespace: true, + egv1a1.StatFormatterRouteKind: true, + egv1a1.StatFormatterRouteRuleName: true, + } + + if err := validateStatName(routeStatName, supportedOperators); err != nil { + return fmt.Errorf("unable to configure Route Stat Name: %w", err) + } + + return nil +} + +func ValidateClusterStatName(clusterStatName string) error { supportedOperators := map[string]bool{ egv1a1.StatFormatterRouteName: true, egv1a1.StatFormatterRouteNamespace: true, @@ -304,15 +321,25 @@ func validateClusterStatName(clusterStatName string) []error { egv1a1.StatFormatterBackendRefs: true, } - var errs []error - re := regexp.MustCompile("%[^%]*%") - matches := re.FindAllString(clusterStatName, -1) + if err := validateStatName(clusterStatName, supportedOperators); err != nil { + return fmt.Errorf("unable to configure Cluster Stat Name: %w", err) + } + + return nil +} + +func validateStatName(statName string, supportedOperators map[string]bool) error { + var unsupportedOperators []string + matches := statNameRegex.FindAllString(statName, -1) for _, operator := range matches { if _, ok := supportedOperators[operator]; !ok { - err := fmt.Errorf("unable to configure Cluster Stat Name with unsupported operator: %s", operator) - errs = append(errs, err) + unsupportedOperators = append(unsupportedOperators, operator) } } - return errs + if len(unsupportedOperators) > 0 { + return fmt.Errorf("unsupported operators: %v", unsupportedOperators) + } + + return nil } diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 2dd26de206..bad9c6f58e 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -458,6 +458,26 @@ func (in *BackendList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendMetrics) DeepCopyInto(out *BackendMetrics) { + *out = *in + if in.RouteStatName != nil { + in, out := &in.RouteStatName, &out.RouteStatName + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendMetrics. +func (in *BackendMetrics) DeepCopy() *BackendMetrics { + if in == nil { + return nil + } + out := new(BackendMetrics) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackendRef) DeepCopyInto(out *BackendRef) { *out = *in @@ -612,6 +632,11 @@ func (in *BackendTelemetry) DeepCopyInto(out *BackendTelemetry) { *out = new(Tracing) (*in).DeepCopyInto(*out) } + if in.Metrics != nil { + in, out := &in.Metrics, &out.Metrics + *out = new(BackendMetrics) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTelemetry. diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index be726b9460..5ac85b0d8c 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -2265,6 +2265,22 @@ spec: Telemetry configures the telemetry settings for the policy target (Gateway or xRoute). This will override the telemetry settings in the EnvoyProxy resource. properties: + metrics: + description: Metrics defines metrics configuration for the backend + or Route. + properties: + routeStatName: + description: |- + RouteStatName defines the value of the Route stat_prefix, determining how the route stats are named. + For more details, see envoy docs: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#config-route-v3-route + The supported operators for this pattern are: + %ROUTE_NAME%: name of Gateway API xRoute resource + %ROUTE_NAMESPACE%: namespace of Gateway API xRoute resource + %ROUTE_KIND%: kind of Gateway API xRoute resource + Example: %ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME% => httproute/my-ns/my-route + Disabled by default. + type: string + type: object tracing: description: Tracing configures the tracing settings for the backend or HTTPRoute. diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index f0fa3b569c..463c189bbb 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -2264,6 +2264,22 @@ spec: Telemetry configures the telemetry settings for the policy target (Gateway or xRoute). This will override the telemetry settings in the EnvoyProxy resource. properties: + metrics: + description: Metrics defines metrics configuration for the backend + or Route. + properties: + routeStatName: + description: |- + RouteStatName defines the value of the Route stat_prefix, determining how the route stats are named. + For more details, see envoy docs: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#config-route-v3-route + The supported operators for this pattern are: + %ROUTE_NAME%: name of Gateway API xRoute resource + %ROUTE_NAMESPACE%: namespace of Gateway API xRoute resource + %ROUTE_KIND%: kind of Gateway API xRoute resource + Example: %ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME% => httproute/my-ns/my-route + Disabled by default. + type: string + type: object tracing: description: Tracing configures the tracing settings for the backend or HTTPRoute. diff --git a/internal/gatewayapi/backendtrafficpolicy.go b/internal/gatewayapi/backendtrafficpolicy.go index a339d3b8c8..032b39bd84 100644 --- a/internal/gatewayapi/backendtrafficpolicy.go +++ b/internal/gatewayapi/backendtrafficpolicy.go @@ -21,6 +21,7 @@ import ( gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" + egv1a1validation "github.com/envoyproxy/gateway/api/v1alpha1/validation" "github.com/envoyproxy/gateway/internal/gatewayapi/resource" "github.com/envoyproxy/gateway/internal/gatewayapi/status" "github.com/envoyproxy/gateway/internal/ir" @@ -705,6 +706,11 @@ func (t *Translator) applyTrafficFeatureToRoute(route RouteContext, x *ir.Xds, policyTargetListener *gwapiv1.SectionName, ) { + routeStatName := "" + if tf.Telemetry != nil && tf.Telemetry.Metrics != nil { + routeStatName = ptr.Deref(tf.Telemetry.Metrics.RouteStatName, "") + } + prefix := irRoutePrefix(route) for _, tcp := range x.TCP { // if listenerName is not nil, only apply to the specific listener @@ -728,6 +734,7 @@ func (t *Translator) applyTrafficFeatureToRoute(route RouteContext, setIfNil(&r.Timeout, tf.Timeout) setIfNil(&r.BackendConnection, tf.BackendConnection) setIfNil(&r.DNS, tf.DNS) + setIfNil(&r.StatName, buildRouteStatName(routeStatName, r.Metadata)) } } } @@ -773,6 +780,7 @@ func (t *Translator) applyTrafficFeatureToRoute(route RouteContext, continue } + r.StatName = buildRouteStatName(routeStatName, r.Metadata) if errs != nil { // Return a 500 direct response r.DirectResponse = &ir.CustomResponse{ @@ -889,6 +897,11 @@ func (t *Translator) buildTrafficFeatures(policy *egv1a1.BackendTrafficPolicy, r errs = errors.Join(errs, err) } + if err = validateTelemetry(policy.Spec.Telemetry); err != nil { + err = perr.WithMessage(err, "Telemetry") + errs = errors.Join(errs, err) + } + cp = buildCompression(policy.Spec.Compression, policy.Spec.Compressor) httpUpgrade = buildHTTPProtocolUpgradeConfig(policy.Spec.HTTPUpgrade) @@ -925,6 +938,11 @@ func (t *Translator) translateBackendTrafficPolicyForGateway( return errs } + routeStatName := "" + if tf.Telemetry != nil && tf.Telemetry.Metrics != nil { + routeStatName = ptr.Deref(tf.Telemetry.Metrics.RouteStatName, "") + } + // Apply IR to all the routes within the specific Gateway // If the feature is already set, then skip it, since it must have // set by a policy attaching to the route @@ -955,6 +973,7 @@ func (t *Translator) translateBackendTrafficPolicyForGateway( setIfNil(&r.TCPKeepalive, tf.TCPKeepalive) setIfNil(&r.Timeout, tf.Timeout) setIfNil(&r.DNS, tf.DNS) + setIfNil(&r.StatName, buildRouteStatName(routeStatName, r.Metadata)) } } @@ -1002,6 +1021,7 @@ func (t *Translator) translateBackendTrafficPolicyForGateway( continue } + setIfNil(&r.StatName, buildRouteStatName(routeStatName, r.Metadata)) if errs != nil { // Return a 500 direct response r.DirectResponse = &ir.CustomResponse{ @@ -1613,3 +1633,33 @@ func buildHTTPProtocolUpgradeConfig(cfgs []*egv1a1.ProtocolUpgradeConfig) []ir.H return result } + +func validateTelemetry(telemetry *egv1a1.BackendTelemetry) error { + if telemetry == nil { + return nil + } + + if telemetry.Metrics != nil && ptr.Deref(telemetry.Metrics.RouteStatName, "") != "" { + return egv1a1validation.ValidateRouteStatName(*telemetry.Metrics.RouteStatName) + } + + return nil +} + +func buildRouteStatName(routeStatName string, metadata *ir.ResourceMetadata) *string { + if routeStatName == "" || metadata == nil { + return nil + } + + statName := strings.ReplaceAll(routeStatName, egv1a1.StatFormatterRouteName, metadata.Name) + statName = strings.ReplaceAll(statName, egv1a1.StatFormatterRouteNamespace, metadata.Namespace) + statName = strings.ReplaceAll(statName, egv1a1.StatFormatterRouteKind, metadata.Kind) + + if metadata.SectionName == "" { + statName = strings.ReplaceAll(statName, egv1a1.StatFormatterRouteRuleName, "-") + } else { + statName = strings.ReplaceAll(statName, egv1a1.StatFormatterRouteRuleName, metadata.SectionName) + } + + return &statName +} diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index a8a20d4ed7..da384ca9de 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -1256,6 +1256,7 @@ func (t *Translator) processTLSRouteParentRefs(tlsRoute *TLSRouteContext, resour Settings: destSettings, Metadata: buildResourceMetadata(tlsRoute, nil), }, + Metadata: buildResourceMetadata(tlsRoute, nil), } irListener.Routes = append(irListener.Routes, irRoute) @@ -1554,9 +1555,9 @@ func (t *Translator) processTCPRouteParentRefs(tcpRoute *TCPRouteContext, resour Destination: &ir.RouteDestination{ Name: destName, Settings: destSettings, - // tcpRoute Must have a single rule, so can use index 0. Metadata: buildResourceMetadata(tcpRoute, tcpRoute.Spec.Rules[0].Name), }, + Metadata: buildResourceMetadata(tcpRoute, nil), } if irListener.TLS != nil { diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-stats.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-stats.in.yaml new file mode 100644 index 0000000000..f97458e671 --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-stats.in.yaml @@ -0,0 +1,118 @@ +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 +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: GRPCRoute + metadata: + namespace: default + name: grpcroute-2 + 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: "/test" + 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 + telemetry: + metrics: + routeStatName: "%ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME%/%ROUTE_NAME%" +- 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 + telemetry: + metrics: + routeStatName: "route=/test,kind=%ROUTE_KIND%,ns=%ROUTE_NAMESPACE%,name=%ROUTE_NAME%" +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + namespace: default + name: policy-for-route-rewrite + spec: + targetRef: + group: gateway.networking.k8s.io + kind: GRPCRoute + name: grpcroute-2 + telemetry: + metrics: + routeStatName: "route=rewrite" diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-stats.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-stats.out.yaml new file mode 100644 index 0000000000..3c6d55786f --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-stats.out.yaml @@ -0,0 +1,496 @@ +backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + name: policy-for-route + namespace: default + spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + telemetry: + metrics: + routeStatName: route=/test,kind=%ROUTE_KIND%,ns=%ROUTE_NAMESPACE%,name=%ROUTE_NAME% + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-2 + namespace: envoy-gateway + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + name: policy-for-route-rewrite + namespace: default + spec: + targetRef: + group: gateway.networking.k8s.io + kind: GRPCRoute + name: grpcroute-2 + telemetry: + metrics: + routeStatName: route=rewrite + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + name: policy-for-gateway + namespace: envoy-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + telemetry: + metrics: + routeStatName: '%ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME%/%ROUTE_NAME%' + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: 'This policy is being overridden by other backendTrafficPolicies + for these routes: [default/grpcroute-2]' + reason: Overridden + status: "True" + type: Overridden + controllerName: gateway.envoyproxy.io/gatewayclass-controller +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 2 + 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 +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + name: gateway-2 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 1 + 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 +grpcRoutes: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: GRPCRoute + metadata: + name: grpcroute-1 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: GRPCRoute + metadata: + name: grpcroute-2 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: httproute-1 + namespace: default + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - name: gateway-2 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: /test + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-2 + namespace: envoy-gateway + sectionName: http +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + ownerReference: + kind: GatewayClass + name: envoy-gateway-class + name: envoy-gateway/gateway-1 + namespace: envoy-gateway-system + envoy-gateway/gateway-2: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-2/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-2 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + ownerReference: + kind: GatewayClass + name: envoy-gateway-class + name: envoy-gateway/gateway-2 + namespace: envoy-gateway-system +xdsIR: + envoy-gateway/gateway-1: + accessLog: + json: + - path: /dev/stdout + globalResources: + proxyServiceCluster: + metadata: + name: envoy-envoy-gateway-gateway-1-196ae069 + namespace: envoy-gateway-system + sectionName: "8080" + name: envoy-gateway/gateway-1 + settings: + - addressType: IP + endpoints: + - host: 7.6.5.4 + port: 8080 + zone: zone1 + metadata: + name: envoy-envoy-gateway-gateway-1-196ae069 + namespace: envoy-gateway-system + sectionName: "8080" + name: envoy-gateway/gateway-1 + protocol: TCP + http: + - address: 0.0.0.0 + externalPort: 80 + hostnames: + - '*' + isHTTP2: true + metadata: + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + metadata: + kind: GRPCRoute + name: grpcroute-1 + namespace: default + name: grpcroute/default/grpcroute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + metadata: + name: service-1 + namespace: default + sectionName: "8080" + name: grpcroute/default/grpcroute-1/rule/0/backend/0 + protocol: GRPC + weight: 1 + hostname: '*' + isHTTP2: true + metadata: + kind: GRPCRoute + name: grpcroute-1 + namespace: default + name: grpcroute/default/grpcroute-1/rule/0/match/-1/* + statName: GRPCRoute/default/grpcroute-1/grpcroute-1 + traffic: + telemetry: + metrics: + routeStatName: '%ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME%/%ROUTE_NAME%' + - destination: + metadata: + kind: GRPCRoute + name: grpcroute-2 + namespace: default + name: grpcroute/default/grpcroute-2/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + metadata: + name: service-1 + namespace: default + sectionName: "8080" + name: grpcroute/default/grpcroute-2/rule/0/backend/0 + protocol: GRPC + weight: 1 + hostname: '*' + isHTTP2: true + metadata: + kind: GRPCRoute + name: grpcroute-2 + namespace: default + name: grpcroute/default/grpcroute-2/rule/0/match/-1/* + statName: route=rewrite + traffic: + telemetry: + metrics: + routeStatName: route=rewrite + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 + envoy-gateway/gateway-2: + accessLog: + json: + - path: /dev/stdout + globalResources: + proxyServiceCluster: + metadata: + name: envoy-envoy-gateway-gateway-2-4a0e4eb9 + namespace: envoy-gateway-system + sectionName: "8080" + name: envoy-gateway/gateway-2 + settings: + - addressType: IP + endpoints: + - host: 7.6.5.4 + port: 8080 + zone: zone1 + metadata: + name: envoy-envoy-gateway-gateway-2-4a0e4eb9 + namespace: envoy-gateway-system + sectionName: "8080" + name: envoy-gateway/gateway-2 + protocol: TCP + http: + - address: 0.0.0.0 + externalPort: 80 + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-2 + namespace: envoy-gateway + sectionName: http + name: envoy-gateway/gateway-2/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + metadata: + name: service-1 + namespace: default + sectionName: "8080" + name: httproute/default/httproute-1/rule/0/backend/0 + protocol: HTTP + weight: 1 + hostname: gateway.envoyproxy.io + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: /test + statName: route=/test,kind=HTTPRoute,ns=default,name=httproute-1 + traffic: + telemetry: + metrics: + routeStatName: route=/test,kind=%ROUTE_KIND%,ns=%ROUTE_NAMESPACE%,name=%ROUTE_NAME% + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-gateway.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-gateway.out.yaml index baec7d2e32..8f52dd299b 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-gateway.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-gateway.out.yaml @@ -317,6 +317,10 @@ xdsIR: loadBalancer: consistentHash: sourceIP: true + metadata: + kind: TCPRoute + name: tls-app-1 + namespace: default name: tcproute/default/tls-app-1 proxyProtocol: version: V2 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-route.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-route.out.yaml index 4200ea08f4..55a421e4b9 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-route.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-route.out.yaml @@ -389,6 +389,10 @@ xdsIR: loadBalancer: consistentHash: sourceIP: true + metadata: + kind: TCPRoute + name: tcp-app-1 + namespace: default name: tcproute/default/tcp-app-1 proxyProtocol: version: V2 diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-for-tcp-listeners.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-for-tcp-listeners.out.yaml index bf50ae96ea..1a58c909c1 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-for-tcp-listeners.out.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-for-tcp-listeners.out.yaml @@ -244,6 +244,10 @@ xdsIR: name: tcproute/default/tcproute-1/rule/-1/backend/0 protocol: TCP weight: 1 + metadata: + kind: TCPRoute + name: tcproute-1 + namespace: default name: tcproute/default/tcproute-1 tls: terminate: @@ -321,6 +325,10 @@ xdsIR: name: tcproute/default/tcproute-1/rule/-1/backend/0 protocol: TCP weight: 1 + metadata: + kind: TCPRoute + name: tcproute-1 + namespace: default name: tcproute/default/tcproute-1 tcpKeepalive: idleTime: 1200 diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-invalid-settings.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-invalid-settings.out.yaml index 588f2d27b1..0e45ef5ca2 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-invalid-settings.out.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-invalid-settings.out.yaml @@ -1008,6 +1008,10 @@ xdsIR: name: tcproute/default/tcp-route-1/rule/-1/backend/0 protocol: TCP weight: 1 + metadata: + kind: TCPRoute + name: tcp-route-1 + namespace: default name: tcproute/default/tcp-route-1 default/gateway-2: accessLog: diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-client-verification-expired-crl.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-client-verification-expired-crl.out.yaml index ee8d3f2784..a158e59366 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-client-verification-expired-crl.out.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-client-verification-expired-crl.out.yaml @@ -713,6 +713,10 @@ xdsIR: name: tcproute/envoy-gateway/tcproute-1/rule/-1/backend/0 protocol: TCP weight: 1 + metadata: + kind: TCPRoute + name: tcproute-1 + namespace: envoy-gateway name: tcproute/envoy-gateway/tcproute-1 tls: terminate: diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-client-verification.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-client-verification.out.yaml index e8ba0842d9..e15b3cd957 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-client-verification.out.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-client-verification.out.yaml @@ -693,6 +693,10 @@ xdsIR: name: tcproute-1 namespace: envoy-gateway name: tcproute/envoy-gateway/tcproute-1/rule/-1 + metadata: + kind: TCPRoute + name: tcproute-1 + namespace: envoy-gateway name: tcproute/envoy-gateway/tcproute-1 tls: terminate: diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol-legacy-mixed.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol-legacy-mixed.out.yaml index c4b3ff1fd0..48528439b1 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol-legacy-mixed.out.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol-legacy-mixed.out.yaml @@ -327,6 +327,10 @@ xdsIR: name: tcproute-1 namespace: envoy-gateway name: tcproute/envoy-gateway/tcproute-1/rule/-1 + metadata: + kind: TCPRoute + name: tcproute-1 + namespace: envoy-gateway name: tcproute/envoy-gateway/tcproute-1 envoy-gateway/gateway-new-api-only: accessLog: diff --git a/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid-ns.out.yaml b/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid-ns.out.yaml index 0504b17b9b..214a30e219 100644 --- a/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid-ns.out.yaml +++ b/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid-ns.out.yaml @@ -304,6 +304,10 @@ xdsIR: name: envoy-gateway namespace: envoy-gateway name: tcproute/envoy-gateway/envoy-gateway/rule/-1 + metadata: + kind: TCPRoute + name: envoy-gateway + namespace: envoy-gateway name: tcproute/envoy-gateway/envoy-gateway tls: terminate: diff --git a/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid.out.yaml b/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid.out.yaml index 5a34dbf42c..e615766d31 100644 --- a/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid.out.yaml +++ b/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid.out.yaml @@ -303,6 +303,10 @@ xdsIR: name: envoy-gateway namespace: envoy-gateway name: tcproute/envoy-gateway/envoy-gateway/rule/-1 + metadata: + kind: TCPRoute + name: envoy-gateway + namespace: envoy-gateway name: tcproute/envoy-gateway/envoy-gateway tls: terminate: diff --git a/internal/gatewayapi/testdata/envoyproxy-tls-settings.out.yaml b/internal/gatewayapi/testdata/envoyproxy-tls-settings.out.yaml index 224f3037d1..9e05786f2e 100644 --- a/internal/gatewayapi/testdata/envoyproxy-tls-settings.out.yaml +++ b/internal/gatewayapi/testdata/envoyproxy-tls-settings.out.yaml @@ -376,6 +376,10 @@ xdsIR: sni: example.com useSystemTrustStore: true weight: 1 + metadata: + kind: TCPRoute + name: envoy-gateway + namespace: envoy-gateway name: tcproute/envoy-gateway/envoy-gateway tls: terminate: diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-mismatch-port-protocol.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-mismatch-port-protocol.out.yaml index ea35dd7b3f..5ff656e57e 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-mismatch-port-protocol.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-mismatch-port-protocol.out.yaml @@ -133,4 +133,8 @@ xdsIR: name: tcproute-1 namespace: default name: tcproute/default/tcproute-1/rule/-1 + metadata: + kind: TCPRoute + name: tcproute-1 + namespace: default name: tcproute/default/tcproute-1 diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-multiple-backends.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-multiple-backends.out.yaml index 5f2266f888..c766ddd253 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-multiple-backends.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-multiple-backends.out.yaml @@ -160,4 +160,8 @@ xdsIR: name: tcproute/default/tcproute-1/rule/-1/backend/1 protocol: TCP weight: 50 + metadata: + kind: TCPRoute + name: tcproute-1 + namespace: default name: tcproute/default/tcproute-1 diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-tls-terminate-and-passthrough.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-tls-terminate-and-passthrough.out.yaml index ac36a5006a..87b3b8f300 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-tls-terminate-and-passthrough.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-tls-terminate-and-passthrough.out.yaml @@ -277,6 +277,10 @@ xdsIR: name: tlsroute/default/tlsroute-1/rule/-1/backend/0 protocol: HTTPS weight: 1 + metadata: + kind: TLSRoute + name: tlsroute-1 + namespace: default name: tlsroute/default/tlsroute-1 tls: inspector: diff --git a/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-tcproutes.out.yaml b/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-tcproutes.out.yaml index ea02c5a35a..5328580cf8 100644 --- a/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-tcproutes.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-tcproutes.out.yaml @@ -175,4 +175,8 @@ xdsIR: name: tcproute/default/tcproute-1/rule/-1/backend/0 protocol: TCP weight: 1 + metadata: + kind: TCPRoute + name: tcproute-1 + namespace: default name: tcproute/default/tcproute-1 diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-tcp-or-tls-port.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-tcp-or-tls-port.out.yaml index e999f83660..a7c87a8580 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-tcp-or-tls-port.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-tcp-or-tls-port.out.yaml @@ -169,4 +169,8 @@ xdsIR: name: tcproute/default/tcproute-1/rule/-1/backend/0 protocol: TCP weight: 1 + metadata: + kind: TCPRoute + name: tcproute-1 + namespace: default name: tcproute/default/tcproute-1 diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-tcp-protocol.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-tcp-protocol.out.yaml index d050c9e785..35d815b18e 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-tcp-protocol.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-tcp-protocol.out.yaml @@ -262,4 +262,8 @@ xdsIR: name: tcproute/default/tcproute-1/rule/-1/backend/0 protocol: TCP weight: 1 + metadata: + kind: TCPRoute + name: tcproute-1 + namespace: default name: tcproute/default/tcproute-1 diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-with-sectionname.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-with-sectionname.out.yaml index e8910b4d62..d7bb13d864 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-with-sectionname.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-with-sectionname.out.yaml @@ -213,6 +213,10 @@ xdsIR: name: tcproute/default/tcproute-1/rule/-1/backend/0 protocol: TCP weight: 1 + metadata: + kind: TCPRoute + name: tcproute-1 + namespace: default name: tcproute/default/tcproute-1 - address: 0.0.0.0 externalPort: 163 @@ -242,4 +246,8 @@ xdsIR: name: tcproute/default/tcproute-2/rule/-1/backend/0 protocol: TCP weight: 1 + metadata: + kind: TCPRoute + name: tcproute-2 + namespace: default name: tcproute/default/tcproute-2 diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-without-sectionname.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-without-sectionname.out.yaml index 5010701ecc..d096feae49 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-without-sectionname.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-without-sectionname.out.yaml @@ -209,6 +209,10 @@ xdsIR: name: tcproute/default/tcproute-1/rule/-1/backend/0 protocol: TCP weight: 1 + metadata: + kind: TCPRoute + name: tcproute-1 + namespace: default name: tcproute/default/tcproute-1 - address: 0.0.0.0 externalPort: 162 @@ -238,4 +242,8 @@ xdsIR: name: tcproute/default/tcproute-1/rule/-1/backend/0 protocol: TCP weight: 1 + metadata: + kind: TCPRoute + name: tcproute-1 + namespace: default name: tcproute/default/tcproute-1 diff --git a/internal/gatewayapi/testdata/tcproute-attaching-to-gateway-with-listener-tls-terminate.out.yaml b/internal/gatewayapi/testdata/tcproute-attaching-to-gateway-with-listener-tls-terminate.out.yaml index 44c12650cf..673ae28de1 100644 --- a/internal/gatewayapi/testdata/tcproute-attaching-to-gateway-with-listener-tls-terminate.out.yaml +++ b/internal/gatewayapi/testdata/tcproute-attaching-to-gateway-with-listener-tls-terminate.out.yaml @@ -219,6 +219,10 @@ xdsIR: name: tcproute/default/tcproute-1/rule/-1/backend/0 protocol: TCP weight: 1 + metadata: + kind: TCPRoute + name: tcproute-1 + namespace: default name: tcproute/default/tcproute-1 tls: terminate: @@ -261,6 +265,10 @@ xdsIR: name: tcproute/default/tcproute-2/rule/-1/backend/0 protocol: TCP weight: 1 + metadata: + kind: TCPRoute + name: tcproute-2 + namespace: default name: tcproute/default/tcproute-2 tls: inspector: diff --git a/internal/gatewayapi/testdata/tcproute-rule-with-multiple-backends-and-zero-weights.out.yaml b/internal/gatewayapi/testdata/tcproute-rule-with-multiple-backends-and-zero-weights.out.yaml index 483e399825..8cc3269631 100644 --- a/internal/gatewayapi/testdata/tcproute-rule-with-multiple-backends-and-zero-weights.out.yaml +++ b/internal/gatewayapi/testdata/tcproute-rule-with-multiple-backends-and-zero-weights.out.yaml @@ -177,4 +177,8 @@ xdsIR: name: tcproute/default/tcproute-1/rule/-1/backend/2 protocol: TCP weight: 3 + metadata: + kind: TCPRoute + name: tcproute-1 + namespace: default name: tcproute/default/tcproute-1 diff --git a/internal/gatewayapi/testdata/tcproute-securitypolicy-with-authorization-client-cidr.out.yaml b/internal/gatewayapi/testdata/tcproute-securitypolicy-with-authorization-client-cidr.out.yaml index 36479a2d7b..f13c4c29b6 100644 --- a/internal/gatewayapi/testdata/tcproute-securitypolicy-with-authorization-client-cidr.out.yaml +++ b/internal/gatewayapi/testdata/tcproute-securitypolicy-with-authorization-client-cidr.out.yaml @@ -664,6 +664,10 @@ xdsIR: name: tcproute/default/tcpr-app-mixed/rule/-1/backend/0 protocol: TCP weight: 1 + metadata: + kind: TCPRoute + name: tcpr-app-mixed + namespace: default name: tcproute/default/tcpr-app-mixed envoy-gateway/gateway-tcp: accessLog: @@ -734,6 +738,10 @@ xdsIR: name: tcproute/default/tcpr-app-foo/rule/-1/backend/0 protocol: TCP weight: 1 + metadata: + kind: TCPRoute + name: tcpr-app-foo + namespace: default name: tcproute/default/tcpr-app-foo - address: 0.0.0.0 externalPort: 8089 @@ -775,4 +783,8 @@ xdsIR: name: tcproute/default/tcpr-app-bar/rule/-1/backend/0 protocol: TCP weight: 1 + metadata: + kind: TCPRoute + name: tcpr-app-bar + namespace: default name: tcproute/default/tcpr-app-bar diff --git a/internal/gatewayapi/testdata/tcproute-with-backend.out.yaml b/internal/gatewayapi/testdata/tcproute-with-backend.out.yaml index b249e08e79..67fa72d926 100644 --- a/internal/gatewayapi/testdata/tcproute-with-backend.out.yaml +++ b/internal/gatewayapi/testdata/tcproute-with-backend.out.yaml @@ -166,4 +166,8 @@ xdsIR: name: tcproute/default/tcproute-1/rule/-1/backend/0 protocol: TCP weight: 1 + metadata: + kind: TCPRoute + name: tcproute-1 + namespace: default name: tcproute/default/tcproute-1 diff --git a/internal/gatewayapi/testdata/tlsroute-attaching-to-gateway.out.yaml b/internal/gatewayapi/testdata/tlsroute-attaching-to-gateway.out.yaml index a8fe5b6f6a..01bdeae294 100644 --- a/internal/gatewayapi/testdata/tlsroute-attaching-to-gateway.out.yaml +++ b/internal/gatewayapi/testdata/tlsroute-attaching-to-gateway.out.yaml @@ -148,6 +148,10 @@ xdsIR: name: tlsroute/default/tlsroute-1/rule/-1/backend/0 protocol: HTTPS weight: 1 + metadata: + kind: TLSRoute + name: tlsroute-1 + namespace: default name: tlsroute/default/tlsroute-1 tls: inspector: diff --git a/internal/gatewayapi/testdata/tlsroute-multiple.out.yaml b/internal/gatewayapi/testdata/tlsroute-multiple.out.yaml index 0321c3838e..b33107517a 100644 --- a/internal/gatewayapi/testdata/tlsroute-multiple.out.yaml +++ b/internal/gatewayapi/testdata/tlsroute-multiple.out.yaml @@ -181,6 +181,10 @@ xdsIR: name: tlsroute/default/tlsroute-1/rule/-1/backend/0 protocol: HTTPS weight: 1 + metadata: + kind: TLSRoute + name: tlsroute-1 + namespace: default name: tlsroute/default/tlsroute-1 tls: inspector: @@ -204,6 +208,10 @@ xdsIR: name: tlsroute/default/tlsroute-2/rule/-1/backend/0 protocol: HTTPS weight: 1 + metadata: + kind: TLSRoute + name: tlsroute-2 + namespace: default name: tlsroute/default/tlsroute-2 tls: inspector: diff --git a/internal/gatewayapi/testdata/tlsroute-with-backend.out.yaml b/internal/gatewayapi/testdata/tlsroute-with-backend.out.yaml index 169a573168..72bf40abfd 100644 --- a/internal/gatewayapi/testdata/tlsroute-with-backend.out.yaml +++ b/internal/gatewayapi/testdata/tlsroute-with-backend.out.yaml @@ -167,6 +167,10 @@ xdsIR: name: tlsroute/default/tlsroute-1/rule/-1/backend/0 protocol: HTTPS weight: 1 + metadata: + kind: TLSRoute + name: tlsroute-1 + namespace: default name: tlsroute/default/tlsroute-1 tls: inspector: diff --git a/internal/gatewayapi/testdata/tlsroute-with-backendref-in-other-namespace-allowed-by-refgrant.out.yaml b/internal/gatewayapi/testdata/tlsroute-with-backendref-in-other-namespace-allowed-by-refgrant.out.yaml index f97c452239..e11ea1a209 100644 --- a/internal/gatewayapi/testdata/tlsroute-with-backendref-in-other-namespace-allowed-by-refgrant.out.yaml +++ b/internal/gatewayapi/testdata/tlsroute-with-backendref-in-other-namespace-allowed-by-refgrant.out.yaml @@ -150,6 +150,10 @@ xdsIR: name: tlsroute/default/tlsroute-1/rule/-1/backend/0 protocol: HTTPS weight: 1 + metadata: + kind: TLSRoute + name: tlsroute-1 + namespace: default name: tlsroute/default/tlsroute-1 tls: inspector: diff --git a/internal/gatewayapi/testdata/tlsroute-with-empty-hostname.out.yaml b/internal/gatewayapi/testdata/tlsroute-with-empty-hostname.out.yaml index 1a74865afd..efe46b743c 100644 --- a/internal/gatewayapi/testdata/tlsroute-with-empty-hostname.out.yaml +++ b/internal/gatewayapi/testdata/tlsroute-with-empty-hostname.out.yaml @@ -147,6 +147,10 @@ xdsIR: name: tlsroute/default/tlsroute-1/rule/-1/backend/0 protocol: HTTPS weight: 1 + metadata: + kind: TLSRoute + name: tlsroute-1 + namespace: default name: tlsroute/default/tlsroute-1 tls: inspector: diff --git a/internal/gatewayapi/testdata/tlsroute-with-empty-listener-hostname.out.yaml b/internal/gatewayapi/testdata/tlsroute-with-empty-listener-hostname.out.yaml index 91e837f19f..216140209d 100644 --- a/internal/gatewayapi/testdata/tlsroute-with-empty-listener-hostname.out.yaml +++ b/internal/gatewayapi/testdata/tlsroute-with-empty-listener-hostname.out.yaml @@ -149,6 +149,10 @@ xdsIR: name: tlsroute/default/tlsroute-1/rule/-1/backend/0 protocol: HTTPS weight: 1 + metadata: + kind: TLSRoute + name: tlsroute-1 + namespace: default name: tlsroute/default/tlsroute-1 tls: inspector: diff --git a/internal/ir/xds.go b/internal/ir/xds.go index 2e801c4dec..bc4f6175a3 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -766,6 +766,8 @@ type HTTPClientTimeout struct { type HTTPRoute struct { // Name of the HTTPRoute Name string `json:"name" yaml:"name"` + // StatName is the name of the route used for statistics and metrics. + StatName *string `json:"statName,omitempty" yaml:"statName,omitempty"` // Hostname that the route matches against Hostname string `json:"hostname" yaml:"hostname,omitempty"` // IsHTTP2 is set if the route is configured to serve HTTP2 traffic @@ -2038,6 +2040,8 @@ type TCPListener struct { type TCPRoute struct { // Name of the TCPRoute. Name string `json:"name" yaml:"name"` + // StatName is the name of the route used for statistics and metrics. + StatName *string `json:"statName,omitempty" yaml:"statName,omitempty"` // TLS holds information for configuring TLS on a listener TLS *TLS `json:"tls,omitempty" yaml:"tls,omitempty"` // Destinations associated with TCP traffic to the service. @@ -2054,6 +2058,8 @@ type TCPRoute struct { HealthCheck *HealthCheck `json:"healthCheck,omitempty" yaml:"healthCheck,omitempty"` // Proxy Protocol Settings ProxyProtocol *ProxyProtocol `json:"proxyProtocol,omitempty" yaml:"proxyProtocol,omitempty"` + // Metadata is used to enrich envoy route metadata with user and provider-specific information + Metadata *ResourceMetadata `json:"metadata,omitempty" yaml:"metadata,omitempty"` // settings of upstream connection BackendConnection *BackendConnection `json:"backendConnection,omitempty" yaml:"backendConnection,omitempty"` // Preconnect configures preconnecting to upstream endpoints diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go index f1e4d5addc..8870551a59 100644 --- a/internal/ir/zz_generated.deepcopy.go +++ b/internal/ir/zz_generated.deepcopy.go @@ -1795,6 +1795,11 @@ func (in *HTTPPathModifier) DeepCopy() *HTTPPathModifier { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) { *out = *in + if in.StatName != nil { + in, out := &in.StatName, &out.StatName + *out = new(string) + **out = **in + } if in.PathMatch != nil { in, out := &in.PathMatch, &out.PathMatch *out = new(StringMatch) @@ -3745,6 +3750,11 @@ func (in *TCPListener) DeepCopy() *TCPListener { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TCPRoute) DeepCopyInto(out *TCPRoute) { *out = *in + if in.StatName != nil { + in, out := &in.StatName, &out.StatName + *out = new(string) + **out = **in + } if in.TLS != nil { in, out := &in.TLS, &out.TLS *out = new(TLS) @@ -3785,6 +3795,11 @@ func (in *TCPRoute) DeepCopyInto(out *TCPRoute) { *out = new(ProxyProtocol) **out = **in } + if in.Metadata != nil { + in, out := &in.Metadata, &out.Metadata + *out = new(ResourceMetadata) + (*in).DeepCopyInto(*out) + } if in.BackendConnection != nil { in, out := &in.BackendConnection, &out.BackendConnection *out = new(BackendConnection) diff --git a/internal/xds/translator/listener.go b/internal/xds/translator/listener.go index 9ace0038c4..896306b5de 100644 --- a/internal/xds/translator/listener.go +++ b/internal/xds/translator/listener.go @@ -629,17 +629,20 @@ func (t *Translator) addXdsTCPFilterChain( isTLSPassthrough := irRoute.TLS != nil && irRoute.TLS.TLSInspectorConfig != nil isTLSTerminate := irRoute.TLS != nil && irRoute.TLS.Terminate != nil - statPrefix := "tcp" - if isTLSPassthrough { - statPrefix = "tls-passthrough" - } + statPrefix := ptr.Deref(irRoute.StatName, "") + if statPrefix == "" { + statPrefix = "tcp" + if isTLSPassthrough { + statPrefix = "tls-passthrough" + } - if isTLSTerminate { - statPrefix = "tls-terminate" - } + if isTLSTerminate { + statPrefix = "tls-terminate" + } - // Append port to the statPrefix. - statPrefix = strings.Join([]string{statPrefix, strconv.Itoa(int(xdsListener.Address.GetSocketAddress().GetPortValue()))}, "-") + // Append port to the statPrefix. + statPrefix = strings.Join([]string{statPrefix, strconv.Itoa(int(xdsListener.Address.GetSocketAddress().GetPortValue()))}, "-") + } filterChain, err := buildTCPFilterChain( irRoute, diff --git a/internal/xds/translator/route.go b/internal/xds/translator/route.go index c255e5f01f..350c169adb 100644 --- a/internal/xds/translator/route.go +++ b/internal/xds/translator/route.go @@ -20,6 +20,7 @@ import ( "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/wrapperspb" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" "github.com/envoyproxy/gateway/internal/ir" "github.com/envoyproxy/gateway/internal/utils/proto" @@ -140,6 +141,9 @@ func buildXdsRoute(httpRoute *ir.HTTPRoute, httpListener *ir.HTTPListener) (*rou } } + // Metrics + router.StatPrefix = ptr.Deref(httpRoute.StatName, "") + // Add per route filter configs to the route, if needed. if err := patchRouteWithPerRouteConfig(router, httpRoute, httpListener); err != nil { return nil, err diff --git a/internal/xds/translator/testdata/in/xds-ir/http-route-metrics-stat.yaml b/internal/xds/translator/testdata/in/xds-ir/http-route-metrics-stat.yaml new file mode 100644 index 0000000000..83c8ea3153 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/http-route-metrics-stat.yaml @@ -0,0 +1,74 @@ +http: +- name: "first-listener" + address: "::" + port: 10080 + hostnames: + - "*" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + routes: + - name: "first-route" + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + pathMatch: + prefix: "/first/" + statName: "route=/first,kind=HTTPRoute,ns=default,name=httproute-1" + hostname: "*" + destination: + name: "first-route-dest" + settings: + - endpoints: + - host: "1.1.1.1" + port: 50001 + weight: 20 + name: "first-route-dest/backend/0" + - endpoints: + - host: "2.2.2.2" + port: 50002 + weight: 40 + name: "first-route-dest/backend/1" + - endpoints: + - host: "3.3.3.3" + port: 50003 + weight: 20 + name: "first-route-dest/backend/2" + - endpoints: + - host: "4.4.4.4" + port: 50004 + weight: 20 + name: "first-route-dest/backend/3" + - name: "second-route" + hostname: "*" + metadata: + kind: HTTPRoute + name: httproute-2 + namespace: default + pathMatch: + prefix: "/second/" + statName: "route=/second,kind=HTTPRoute,ns=default,name=httproute-2" + destination: + name: "second-route-dest" + settings: + - endpoints: + - host: "1.1.1.1" + port: 50001 + weight: 20 + name: "second-route-dest/backend/0" + - endpoints: + - host: "2.2.2.2" + port: 50002 + weight: 40 + name: "second-route-dest/backend/1" + - endpoints: + - host: "3.3.3.3" + port: 50003 + weight: 20 + name: "second-route-dest/backend/2" + - endpoints: + - host: "4.4.4.4" + port: 50004 + weight: 20 + name: "second-route-dest/backend/3" diff --git a/internal/xds/translator/testdata/in/xds-ir/tcp-route-metrics-stat.yaml b/internal/xds/translator/testdata/in/xds-ir/tcp-route-metrics-stat.yaml new file mode 100644 index 0000000000..3f5183dadd --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/tcp-route-metrics-stat.yaml @@ -0,0 +1,20 @@ +tcp: +- name: "tcp-listener-simple" + address: "::" + port: 10080 + routes: + - name: "tcp-route-simple" + metadata: + kind: TCPRoute + name: tcproute-1 + namespace: default + destination: + name: "tcp-route-simple-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 + - host: "5.6.7.8" + port: 50001 + name: "tcp-route-simple-dest/backend/0" + statName: "route=/test,kind=TCPRoute,ns=default,name=tcproute-1" diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.clusters.yaml new file mode 100644 index 0000000000..7e9eb80719 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.clusters.yaml @@ -0,0 +1,48 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_PREFERRED + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + ignoreHealthOnHostRemoval: true + lbPolicy: LEAST_REQUEST + loadBalancingPolicy: + policies: + - typedExtensionConfig: + name: envoy.load_balancing_policies.least_request + typedConfig: + '@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest + localityLbConfig: + localityWeightedLbConfig: {} + name: first-route-dest + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_PREFERRED + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: second-route-dest + ignoreHealthOnHostRemoval: true + lbPolicy: LEAST_REQUEST + loadBalancingPolicy: + policies: + - typedExtensionConfig: + name: envoy.load_balancing_policies.least_request + typedConfig: + '@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest + localityLbConfig: + localityWeightedLbConfig: {} + name: second-route-dest + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.endpoints.yaml new file mode 100644 index 0000000000..7e9e33dae5 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.endpoints.yaml @@ -0,0 +1,84 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.1.1.1 + portValue: 50001 + loadBalancingWeight: 1 + loadBalancingWeight: 20 + locality: + region: first-route-dest/backend/0 + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 2.2.2.2 + portValue: 50002 + loadBalancingWeight: 1 + loadBalancingWeight: 40 + locality: + region: first-route-dest/backend/1 + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 3.3.3.3 + portValue: 50003 + loadBalancingWeight: 1 + loadBalancingWeight: 20 + locality: + region: first-route-dest/backend/2 + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 4.4.4.4 + portValue: 50004 + loadBalancingWeight: 1 + loadBalancingWeight: 20 + locality: + region: first-route-dest/backend/3 +- clusterName: second-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.1.1.1 + portValue: 50001 + loadBalancingWeight: 1 + loadBalancingWeight: 20 + locality: + region: second-route-dest/backend/0 + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 2.2.2.2 + portValue: 50002 + loadBalancingWeight: 1 + loadBalancingWeight: 40 + locality: + region: second-route-dest/backend/1 + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 3.3.3.3 + portValue: 50003 + loadBalancingWeight: 1 + loadBalancingWeight: 20 + locality: + region: second-route-dest/backend/2 + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 4.4.4.4 + portValue: 50004 + loadBalancingWeight: 1 + loadBalancingWeight: 20 + locality: + region: second-route-dest/backend/3 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.listeners.yaml new file mode 100644 index 0000000000..5dd5e46e3c --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.listeners.yaml @@ -0,0 +1,35 @@ +- address: + socketAddress: + address: '::' + portValue: 10080 + defaultFilterChain: + filters: + - name: envoy.filters.network.http_connection_manager + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + commonHttpProtocolOptions: + headersWithUnderscoresAction: REJECT_REQUEST + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 + maxConcurrentStreams: 100 + httpFilters: + - name: envoy.filters.http.router + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + suppressEnvoyHeaders: true + mergeSlashes: true + normalizePath: true + pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http-10080 + useRemoteAddress: true + name: first-listener + maxConnectionsToAcceptPerSocketEvent: 1 + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.routes.yaml new file mode 100644 index 0000000000..c032a95046 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.routes.yaml @@ -0,0 +1,37 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + pathSeparatedPrefix: /first + metadata: + filterMetadata: + envoy-gateway: + resources: + - kind: HTTPRoute + name: httproute-1 + namespace: default + name: first-route + route: + cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket + statPrefix: route=/first,kind=HTTPRoute,ns=default,name=httproute-1 + - match: + pathSeparatedPrefix: /second + metadata: + filterMetadata: + envoy-gateway: + resources: + - kind: HTTPRoute + name: httproute-2 + namespace: default + name: second-route + route: + cluster: second-route-dest + upgradeConfigs: + - upgradeType: websocket + statPrefix: route=/second,kind=HTTPRoute,ns=default,name=httproute-2 diff --git a/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.clusters.yaml new file mode 100644 index 0000000000..b66d2ea80c --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.clusters.yaml @@ -0,0 +1,24 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_PREFERRED + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: tcp-route-simple-dest + ignoreHealthOnHostRemoval: true + lbPolicy: LEAST_REQUEST + loadBalancingPolicy: + policies: + - typedExtensionConfig: + name: envoy.load_balancing_policies.least_request + typedConfig: + '@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest + localityLbConfig: + localityWeightedLbConfig: {} + name: tcp-route-simple-dest + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.endpoints.yaml new file mode 100644 index 0000000000..7eb06a08f4 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.endpoints.yaml @@ -0,0 +1,18 @@ +- clusterName: tcp-route-simple-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + - endpoint: + address: + socketAddress: + address: 5.6.7.8 + portValue: 50001 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: tcp-route-simple-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.listeners.yaml new file mode 100644 index 0000000000..388ebd6088 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.listeners.yaml @@ -0,0 +1,15 @@ +- address: + socketAddress: + address: '::' + portValue: 10080 + filterChains: + - filters: + - name: envoy.filters.network.tcp_proxy + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + cluster: tcp-route-simple-dest + statPrefix: route=/test,kind=TCPRoute,ns=default,name=tcproute-1 + name: tcp-route-simple + maxConnectionsToAcceptPerSocketEvent: 1 + name: tcp-listener-simple + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.routes.yaml new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.routes.yaml @@ -0,0 +1 @@ +[] diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index 1d1086fb7d..00ba1403e4 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -368,6 +368,20 @@ _Appears in:_ | `zone` | _string_ | false | | Zone defines the service zone of the backend endpoint. | +#### BackendMetrics + + + + + +_Appears in:_ +- [BackendTelemetry](#backendtelemetry) + +| Field | Type | Required | Default | Description | +| --- | --- | --- | --- | --- | +| `routeStatName` | _string_ | false | | RouteStatName defines the value of the Route stat_prefix, determining how the route stats are named.
For more details, see envoy docs: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#config-route-v3-route
The supported operators for this pattern are:
%ROUTE_NAME%: name of Gateway API xRoute resource
%ROUTE_NAMESPACE%: namespace of Gateway API xRoute resource
%ROUTE_KIND%: kind of Gateway API xRoute resource
Example: %ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME% => httproute/my-ns/my-route
Disabled by default. | + + #### BackendRef @@ -478,6 +492,7 @@ _Appears in:_ | Field | Type | Required | Default | Description | | --- | --- | --- | --- | --- | | `tracing` | _[Tracing](#tracing)_ | false | | Tracing configures the tracing settings for the backend or HTTPRoute. | +| `metrics` | _[BackendMetrics](#backendmetrics)_ | false | | Metrics defines metrics configuration for the backend or Route. | #### BackendTrafficPolicy diff --git a/test/e2e/testdata/httproute-metrics-stat.yaml b/test/e2e/testdata/httproute-metrics-stat.yaml new file mode 100644 index 0000000000..678ef0abcd --- /dev/null +++ b/test/e2e/testdata/httproute-metrics-stat.yaml @@ -0,0 +1,31 @@ +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: http-route-stat-name + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - matches: + - path: + type: PathPrefix + value: /foo + backendRefs: + - name: infra-backend-v1 + port: 8080 +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: BackendTrafficPolicy +metadata: + name: http-route-stat-name + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: http-route-stat-name + telemetry: + metrics: + routeStatName: "%ROUTE_NAMESPACE%/%ROUTE_NAME%" diff --git a/test/e2e/testdata/tcproute-metrics-stat.yaml b/test/e2e/testdata/tcproute-metrics-stat.yaml new file mode 100644 index 0000000000..553901bfd5 --- /dev/null +++ b/test/e2e/testdata/tcproute-metrics-stat.yaml @@ -0,0 +1,42 @@ +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: tcp-stat-name-backend-gateway + namespace: gateway-conformance-infra +spec: + gatewayClassName: "{GATEWAY_CLASS_NAME}" + listeners: + - name: ip + protocol: TCP + port: 8080 + allowedRoutes: + kinds: + - kind: TCPRoute +--- +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: TCPRoute +metadata: + name: tcp-route-stat-name + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: tcp-stat-name-backend-gateway + sectionName: ip + rules: + - backendRefs: + - name: infra-backend-v1 + port: 8080 +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: BackendTrafficPolicy +metadata: + name: tcp-route-stat-name + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: gateway.networking.k8s.io + kind: TCPRoute + name: tcp-route-stat-name + telemetry: + metrics: + routeStatName: "%ROUTE_NAMESPACE%/%ROUTE_NAME%" diff --git a/test/e2e/tests/stat_name.go b/test/e2e/tests/stat_name.go index 9012c2099b..754b2476c8 100644 --- a/test/e2e/tests/stat_name.go +++ b/test/e2e/tests/stat_name.go @@ -25,11 +25,11 @@ import ( ) func init() { - ConformanceTests = append(ConformanceTests, StatNameTest) + ConformanceTests = append(ConformanceTests, ClusterStatNameTest, HTTPRouteStatNameTest, TCPRouteStatNameTest) } -var StatNameTest = suite.ConformanceTest{ - ShortName: "StatName", +var ClusterStatNameTest = suite.ConformanceTest{ + ShortName: "ClusterStatName", Description: "Make sure metric is working", Manifests: []string{"testdata/envoyproxy-stat-name.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { @@ -85,3 +85,78 @@ var StatNameTest = suite.ConformanceTest{ }) }, } + +var HTTPRouteStatNameTest = suite.ConformanceTest{ + ShortName: "HTTPRouteStatNameTest", + Description: "Make sure per http route metrics is working", + Manifests: []string{"testdata/httproute-metrics-stat.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "http-route-stat-name", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + + t.Run("prometheus", func(t *testing.T) { + expectedResponse := httputils.ExpectedResponse{ + Request: httputils.Request{ + Path: "/foo", + }, + Response: httputils.Response{ + StatusCode: 200, + }, + Namespace: ns, + } + // make sure listener is ready + httputils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse) + verifyMetrics(t, suite, `envoy_vhost_route_upstream_rq{envoy_route="gateway-conformance-infra/http-route-stat-name"}`) + }) + }, +} + +var TCPRouteStatNameTest = suite.ConformanceTest{ + ShortName: "TCPRouteStatNameTest", + Description: "Make sure per tcp route metrics is working", + Manifests: []string{"testdata/tcproute-metrics-stat.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "tcp-route-stat-name", Namespace: ns} + gwNN := types.NamespacedName{Name: "tcp-stat-name-backend-gateway", Namespace: ns} + gwAddr := GatewayAndTCPRoutesMustBeAccepted(t, suite.Client, &suite.TimeoutConfig, suite.ControllerName, NewGatewayRef(gwNN), routeNN) + + t.Run("prometheus", func(t *testing.T) { + expectedResponse := httputils.ExpectedResponse{ + Request: httputils.Request{ + Path: "/foo", + }, + Response: httputils.Response{ + StatusCode: 200, + }, + Namespace: ns, + } + + // make sure listener is ready + httputils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse) + verifyMetrics(t, suite, `envoy_tcp_downstream_cx_total{envoy_tcp_prefix="gateway-conformance-infra/tcp-route-stat-name"}`) + }) + }, +} + +func verifyMetrics(t *testing.T, suite *suite.ConformanceTestSuite, promQuery string) { + if err := wait.PollUntilContextTimeout(context.TODO(), 3*time.Second, time.Minute, true, func(ctx context.Context) (done bool, err error) { + v, err := prometheus.QueryPrometheus(suite.Client, promQuery) + if err != nil { + tlog.Logf(t, "failed to query prometheus: %v", err) + return false, err + } + if v != nil && v.Type() == model.ValVector { + vectorVal := v.(model.Vector) + if len(vectorVal) == 1 { + tlog.Logf(t, "got expected value: %v", v) + return true, nil + } + } + return false, nil + }); err != nil { + t.Errorf("failed to get expected response for the last (fourth) request: %v", err) + } +} diff --git a/test/helm/gateway-crds-helm/all.out.yaml b/test/helm/gateway-crds-helm/all.out.yaml index 63dc101fdd..d577712bf0 100644 --- a/test/helm/gateway-crds-helm/all.out.yaml +++ b/test/helm/gateway-crds-helm/all.out.yaml @@ -23398,6 +23398,22 @@ spec: Telemetry configures the telemetry settings for the policy target (Gateway or xRoute). This will override the telemetry settings in the EnvoyProxy resource. properties: + metrics: + description: Metrics defines metrics configuration for the backend + or Route. + properties: + routeStatName: + description: |- + RouteStatName defines the value of the Route stat_prefix, determining how the route stats are named. + For more details, see envoy docs: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#config-route-v3-route + The supported operators for this pattern are: + %ROUTE_NAME%: name of Gateway API xRoute resource + %ROUTE_NAMESPACE%: namespace of Gateway API xRoute resource + %ROUTE_KIND%: kind of Gateway API xRoute resource + Example: %ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME% => httproute/my-ns/my-route + Disabled by default. + type: string + type: object tracing: description: Tracing configures the tracing settings for the backend or HTTPRoute. diff --git a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml index ae2d5c6e12..849cea47cc 100644 --- a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml +++ b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml @@ -2742,6 +2742,22 @@ spec: Telemetry configures the telemetry settings for the policy target (Gateway or xRoute). This will override the telemetry settings in the EnvoyProxy resource. properties: + metrics: + description: Metrics defines metrics configuration for the backend + or Route. + properties: + routeStatName: + description: |- + RouteStatName defines the value of the Route stat_prefix, determining how the route stats are named. + For more details, see envoy docs: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#config-route-v3-route + The supported operators for this pattern are: + %ROUTE_NAME%: name of Gateway API xRoute resource + %ROUTE_NAMESPACE%: namespace of Gateway API xRoute resource + %ROUTE_KIND%: kind of Gateway API xRoute resource + Example: %ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME% => httproute/my-ns/my-route + Disabled by default. + type: string + type: object tracing: description: Tracing configures the tracing settings for the backend or HTTPRoute.