2023-03-28 18:39:22 +00:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
2023-08-11 13:12:13 +00:00
|
|
|
// SPDX-License-Identifier: BUSL-1.1
|
2023-03-28 18:39:22 +00:00
|
|
|
|
2019-07-12 19:16:21 +00:00
|
|
|
package xds
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
2020-04-16 23:24:11 +00:00
|
|
|
"time"
|
2019-07-12 19:16:21 +00:00
|
|
|
|
2021-02-26 22:23:15 +00:00
|
|
|
envoy_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
|
2020-12-23 17:50:28 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
2022-06-15 19:58:28 +00:00
|
|
|
"google.golang.org/protobuf/types/known/durationpb"
|
2020-12-23 17:50:28 +00:00
|
|
|
|
2020-04-16 23:24:11 +00:00
|
|
|
"github.com/hashicorp/consul/agent/structs"
|
2019-07-12 19:16:21 +00:00
|
|
|
)
|
|
|
|
|
2020-09-02 21:13:50 +00:00
|
|
|
func TestEnvoyLBConfig_InjectToRouteAction(t *testing.T) {
|
|
|
|
var tests = []struct {
|
|
|
|
name string
|
2020-09-11 15:21:43 +00:00
|
|
|
lb *structs.LoadBalancer
|
2021-02-26 22:23:15 +00:00
|
|
|
expected *envoy_route_v3.RouteAction
|
2020-09-02 21:13:50 +00:00
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "empty",
|
2020-09-11 15:21:43 +00:00
|
|
|
lb: &structs.LoadBalancer{
|
2020-09-02 21:13:50 +00:00
|
|
|
Policy: "",
|
|
|
|
},
|
|
|
|
// we only modify route actions for hash-based LB policies
|
2021-02-26 22:23:15 +00:00
|
|
|
expected: &envoy_route_v3.RouteAction{},
|
2020-09-02 21:13:50 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "least request",
|
2020-09-11 15:21:43 +00:00
|
|
|
lb: &structs.LoadBalancer{
|
2020-09-02 21:13:50 +00:00
|
|
|
Policy: structs.LBPolicyLeastRequest,
|
|
|
|
LeastRequestConfig: &structs.LeastRequestConfig{
|
|
|
|
ChoiceCount: 3,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
// we only modify route actions for hash-based LB policies
|
2021-02-26 22:23:15 +00:00
|
|
|
expected: &envoy_route_v3.RouteAction{},
|
2020-09-02 21:13:50 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "headers",
|
2020-09-11 15:21:43 +00:00
|
|
|
lb: &structs.LoadBalancer{
|
2020-09-02 21:13:50 +00:00
|
|
|
Policy: "ring_hash",
|
|
|
|
RingHashConfig: &structs.RingHashConfig{
|
|
|
|
MinimumRingSize: 3,
|
|
|
|
MaximumRingSize: 7,
|
|
|
|
},
|
|
|
|
HashPolicies: []structs.HashPolicy{
|
|
|
|
{
|
|
|
|
Field: structs.HashPolicyHeader,
|
|
|
|
FieldValue: "x-route-key",
|
|
|
|
Terminal: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2021-02-26 22:23:15 +00:00
|
|
|
expected: &envoy_route_v3.RouteAction{
|
|
|
|
HashPolicy: []*envoy_route_v3.RouteAction_HashPolicy{
|
2020-09-02 21:13:50 +00:00
|
|
|
{
|
2021-02-26 22:23:15 +00:00
|
|
|
PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_Header_{
|
|
|
|
Header: &envoy_route_v3.RouteAction_HashPolicy_Header{
|
2020-09-02 21:13:50 +00:00
|
|
|
HeaderName: "x-route-key",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Terminal: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "cookies",
|
2020-09-11 15:21:43 +00:00
|
|
|
lb: &structs.LoadBalancer{
|
2020-09-02 21:13:50 +00:00
|
|
|
Policy: structs.LBPolicyMaglev,
|
|
|
|
HashPolicies: []structs.HashPolicy{
|
|
|
|
{
|
|
|
|
Field: structs.HashPolicyCookie,
|
|
|
|
FieldValue: "red-velvet",
|
|
|
|
Terminal: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Field: structs.HashPolicyCookie,
|
|
|
|
FieldValue: "oatmeal",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2021-02-26 22:23:15 +00:00
|
|
|
expected: &envoy_route_v3.RouteAction{
|
|
|
|
HashPolicy: []*envoy_route_v3.RouteAction_HashPolicy{
|
2020-09-02 21:13:50 +00:00
|
|
|
{
|
2021-02-26 22:23:15 +00:00
|
|
|
PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_Cookie_{
|
|
|
|
Cookie: &envoy_route_v3.RouteAction_HashPolicy_Cookie{
|
2020-09-02 21:13:50 +00:00
|
|
|
Name: "red-velvet",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Terminal: true,
|
|
|
|
},
|
|
|
|
{
|
2021-02-26 22:23:15 +00:00
|
|
|
PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_Cookie_{
|
|
|
|
Cookie: &envoy_route_v3.RouteAction_HashPolicy_Cookie{
|
2020-09-02 21:13:50 +00:00
|
|
|
Name: "oatmeal",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2020-09-12 00:34:03 +00:00
|
|
|
{
|
|
|
|
name: "non-zero session ttl gets zeroed out",
|
|
|
|
lb: &structs.LoadBalancer{
|
|
|
|
Policy: structs.LBPolicyMaglev,
|
|
|
|
HashPolicies: []structs.HashPolicy{
|
|
|
|
{
|
|
|
|
Field: structs.HashPolicyCookie,
|
|
|
|
FieldValue: "oatmeal",
|
|
|
|
CookieConfig: &structs.CookieConfig{
|
|
|
|
TTL: 10 * time.Second,
|
|
|
|
Session: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2021-02-26 22:23:15 +00:00
|
|
|
expected: &envoy_route_v3.RouteAction{
|
|
|
|
HashPolicy: []*envoy_route_v3.RouteAction_HashPolicy{
|
2020-09-12 00:34:03 +00:00
|
|
|
{
|
2021-02-26 22:23:15 +00:00
|
|
|
PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_Cookie_{
|
|
|
|
Cookie: &envoy_route_v3.RouteAction_HashPolicy_Cookie{
|
2020-09-12 00:34:03 +00:00
|
|
|
Name: "oatmeal",
|
2022-05-25 01:44:54 +00:00
|
|
|
Ttl: durationpb.New(0 * time.Second),
|
2020-09-12 00:34:03 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "zero value ttl omitted if not session cookie",
|
|
|
|
lb: &structs.LoadBalancer{
|
|
|
|
Policy: structs.LBPolicyMaglev,
|
|
|
|
HashPolicies: []structs.HashPolicy{
|
|
|
|
{
|
|
|
|
Field: structs.HashPolicyCookie,
|
|
|
|
FieldValue: "oatmeal",
|
|
|
|
CookieConfig: &structs.CookieConfig{
|
|
|
|
Path: "/oven",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2021-02-26 22:23:15 +00:00
|
|
|
expected: &envoy_route_v3.RouteAction{
|
|
|
|
HashPolicy: []*envoy_route_v3.RouteAction_HashPolicy{
|
2020-09-12 00:34:03 +00:00
|
|
|
{
|
2021-02-26 22:23:15 +00:00
|
|
|
PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_Cookie_{
|
|
|
|
Cookie: &envoy_route_v3.RouteAction_HashPolicy_Cookie{
|
2020-09-12 00:34:03 +00:00
|
|
|
Name: "oatmeal",
|
|
|
|
Path: "/oven",
|
|
|
|
Ttl: nil,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2020-09-02 21:13:50 +00:00
|
|
|
{
|
|
|
|
name: "source addr",
|
2020-09-11 15:21:43 +00:00
|
|
|
lb: &structs.LoadBalancer{
|
2020-09-02 21:13:50 +00:00
|
|
|
Policy: structs.LBPolicyMaglev,
|
|
|
|
HashPolicies: []structs.HashPolicy{
|
|
|
|
{
|
|
|
|
SourceIP: true,
|
|
|
|
Terminal: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2021-02-26 22:23:15 +00:00
|
|
|
expected: &envoy_route_v3.RouteAction{
|
|
|
|
HashPolicy: []*envoy_route_v3.RouteAction_HashPolicy{
|
2020-09-02 21:13:50 +00:00
|
|
|
{
|
2021-02-26 22:23:15 +00:00
|
|
|
PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_ConnectionProperties_{
|
|
|
|
ConnectionProperties: &envoy_route_v3.RouteAction_HashPolicy_ConnectionProperties{
|
2020-09-02 21:13:50 +00:00
|
|
|
SourceIp: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Terminal: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "kitchen sink",
|
2020-09-11 15:21:43 +00:00
|
|
|
lb: &structs.LoadBalancer{
|
2020-09-02 21:13:50 +00:00
|
|
|
Policy: structs.LBPolicyMaglev,
|
|
|
|
HashPolicies: []structs.HashPolicy{
|
|
|
|
{
|
|
|
|
SourceIP: true,
|
|
|
|
Terminal: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Field: structs.HashPolicyCookie,
|
|
|
|
FieldValue: "oatmeal",
|
|
|
|
CookieConfig: &structs.CookieConfig{
|
|
|
|
TTL: 10 * time.Second,
|
|
|
|
Path: "/oven",
|
|
|
|
},
|
|
|
|
},
|
2020-09-12 00:34:03 +00:00
|
|
|
{
|
|
|
|
Field: structs.HashPolicyCookie,
|
|
|
|
FieldValue: "chocolate-chip",
|
|
|
|
CookieConfig: &structs.CookieConfig{
|
|
|
|
Session: true,
|
|
|
|
Path: "/oven",
|
|
|
|
},
|
|
|
|
},
|
2020-09-02 21:13:50 +00:00
|
|
|
{
|
|
|
|
Field: structs.HashPolicyHeader,
|
|
|
|
FieldValue: "special-header",
|
|
|
|
Terminal: true,
|
|
|
|
},
|
2023-08-03 19:03:02 +00:00
|
|
|
{
|
|
|
|
Field: structs.HashPolicyQueryParam,
|
|
|
|
FieldValue: "my-pretty-param",
|
|
|
|
Terminal: true,
|
|
|
|
},
|
2020-09-02 21:13:50 +00:00
|
|
|
},
|
|
|
|
},
|
2021-02-26 22:23:15 +00:00
|
|
|
expected: &envoy_route_v3.RouteAction{
|
|
|
|
HashPolicy: []*envoy_route_v3.RouteAction_HashPolicy{
|
2020-09-02 21:13:50 +00:00
|
|
|
{
|
2021-02-26 22:23:15 +00:00
|
|
|
PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_ConnectionProperties_{
|
|
|
|
ConnectionProperties: &envoy_route_v3.RouteAction_HashPolicy_ConnectionProperties{
|
2020-09-02 21:13:50 +00:00
|
|
|
SourceIp: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Terminal: true,
|
|
|
|
},
|
|
|
|
{
|
2021-02-26 22:23:15 +00:00
|
|
|
PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_Cookie_{
|
|
|
|
Cookie: &envoy_route_v3.RouteAction_HashPolicy_Cookie{
|
2020-09-02 21:13:50 +00:00
|
|
|
Name: "oatmeal",
|
2022-05-25 01:44:54 +00:00
|
|
|
Ttl: durationpb.New(10 * time.Second),
|
2020-09-02 21:13:50 +00:00
|
|
|
Path: "/oven",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2020-09-12 00:34:03 +00:00
|
|
|
{
|
2021-02-26 22:23:15 +00:00
|
|
|
PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_Cookie_{
|
|
|
|
Cookie: &envoy_route_v3.RouteAction_HashPolicy_Cookie{
|
2020-09-12 00:34:03 +00:00
|
|
|
Name: "chocolate-chip",
|
2022-05-25 01:44:54 +00:00
|
|
|
Ttl: durationpb.New(0 * time.Second),
|
2020-09-12 00:34:03 +00:00
|
|
|
Path: "/oven",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2020-09-02 21:13:50 +00:00
|
|
|
{
|
2021-02-26 22:23:15 +00:00
|
|
|
PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_Header_{
|
|
|
|
Header: &envoy_route_v3.RouteAction_HashPolicy_Header{
|
2020-09-02 21:13:50 +00:00
|
|
|
HeaderName: "special-header",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Terminal: true,
|
|
|
|
},
|
2023-08-03 19:03:02 +00:00
|
|
|
{
|
|
|
|
PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_QueryParameter_{
|
|
|
|
QueryParameter: &envoy_route_v3.RouteAction_HashPolicy_QueryParameter{
|
|
|
|
Name: "my-pretty-param",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Terminal: true,
|
|
|
|
},
|
2020-09-02 21:13:50 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range tests {
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
2021-02-26 22:23:15 +00:00
|
|
|
var ra envoy_route_v3.RouteAction
|
2020-09-02 21:13:50 +00:00
|
|
|
err := injectLBToRouteAction(tc.lb, &ra)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2021-02-22 21:00:15 +00:00
|
|
|
require.Equal(t, tc.expected, &ra)
|
2020-09-02 21:13:50 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|