mirror of https://github.com/hashicorp/consul
Restructure structs and other PR comments
parent
0236e169bb
commit
63f79e5f9b
|
@ -745,9 +745,11 @@ func (c *compiler) getSplitterNode(sid structs.ServiceID) (*structs.DiscoveryGra
|
|||
// with distinct hash-based load balancer configs specified in their service resolvers.
|
||||
// We cannot apply multiple hash policies to a splitter node's route action.
|
||||
// Therefore, we attach the first hash-based load balancer config we encounter.
|
||||
if !hasLB && node.LoadBalancer.IsHashBased() {
|
||||
splitNode.LoadBalancer = node.LoadBalancer
|
||||
hasLB = true
|
||||
if !hasLB {
|
||||
if lb := node.LoadBalancer; lb != nil && lb.EnvoyLBConfig != nil && lb.EnvoyLBConfig.IsHashBased() {
|
||||
splitNode.LoadBalancer = node.LoadBalancer
|
||||
hasLB = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1761,14 +1761,16 @@ func testcase_AllBellsAndWhistles() compileTestCase {
|
|||
"prod": {Filter: "ServiceMeta.env == prod"},
|
||||
"qa": {Filter: "ServiceMeta.env == qa"},
|
||||
},
|
||||
LoadBalancer: structs.LoadBalancer{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: structs.RingHashConfig{
|
||||
MaximumRingSize: 100,
|
||||
},
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
SourceAddress: true,
|
||||
LoadBalancer: &structs.LoadBalancer{
|
||||
EnvoyLBConfig: &structs.EnvoyLBConfig{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: &structs.RingHashConfig{
|
||||
MaximumRingSize: 100,
|
||||
},
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
SourceIP: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1833,14 +1835,16 @@ func testcase_AllBellsAndWhistles() compileTestCase {
|
|||
NextNode: "resolver:v3.main.default.dc1",
|
||||
},
|
||||
},
|
||||
LoadBalancer: structs.LoadBalancer{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: structs.RingHashConfig{
|
||||
MaximumRingSize: 100,
|
||||
},
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
SourceAddress: true,
|
||||
LoadBalancer: &structs.LoadBalancer{
|
||||
EnvoyLBConfig: &structs.EnvoyLBConfig{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: &structs.RingHashConfig{
|
||||
MaximumRingSize: 100,
|
||||
},
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
SourceIP: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1852,14 +1856,16 @@ func testcase_AllBellsAndWhistles() compileTestCase {
|
|||
ConnectTimeout: 5 * time.Second,
|
||||
Target: "prod.redirected.default.dc1",
|
||||
},
|
||||
LoadBalancer: structs.LoadBalancer{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: structs.RingHashConfig{
|
||||
MaximumRingSize: 100,
|
||||
},
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
SourceAddress: true,
|
||||
LoadBalancer: &structs.LoadBalancer{
|
||||
EnvoyLBConfig: &structs.EnvoyLBConfig{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: &structs.RingHashConfig{
|
||||
MaximumRingSize: 100,
|
||||
},
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
SourceIP: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2275,24 +2281,28 @@ func testcase_LBConfig() compileTestCase {
|
|||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: "service-resolver",
|
||||
Name: "foo",
|
||||
LoadBalancer: structs.LoadBalancer{
|
||||
Policy: "least_request",
|
||||
LeastRequestConfig: structs.LeastRequestConfig{
|
||||
ChoiceCount: 3,
|
||||
LoadBalancer: &structs.LoadBalancer{
|
||||
EnvoyLBConfig: &structs.EnvoyLBConfig{
|
||||
Policy: "least_request",
|
||||
LeastRequestConfig: &structs.LeastRequestConfig{
|
||||
ChoiceCount: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: "service-resolver",
|
||||
Name: "bar",
|
||||
LoadBalancer: structs.LoadBalancer{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: structs.RingHashConfig{
|
||||
MaximumRingSize: 101,
|
||||
},
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
SourceAddress: true,
|
||||
LoadBalancer: &structs.LoadBalancer{
|
||||
EnvoyLBConfig: &structs.EnvoyLBConfig{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: &structs.RingHashConfig{
|
||||
MaximumRingSize: 101,
|
||||
},
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
SourceIP: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2300,13 +2310,19 @@ func testcase_LBConfig() compileTestCase {
|
|||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: "service-resolver",
|
||||
Name: "baz",
|
||||
LoadBalancer: structs.LoadBalancer{
|
||||
Policy: "maglev",
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
Field: "cookie",
|
||||
FieldMatchValue: "chocolate-chip",
|
||||
Terminal: true,
|
||||
LoadBalancer: &structs.LoadBalancer{
|
||||
EnvoyLBConfig: &structs.EnvoyLBConfig{
|
||||
Policy: "maglev",
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
Field: "cookie",
|
||||
FieldValue: "chocolate-chip",
|
||||
CookieConfig: &structs.CookieConfig{
|
||||
TTL: 2 * time.Minute,
|
||||
Path: "/bowl",
|
||||
},
|
||||
Terminal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2336,14 +2352,16 @@ func testcase_LBConfig() compileTestCase {
|
|||
},
|
||||
// The LB config from bar is attached because splitters only care about hash-based policies,
|
||||
// and it's the config from bar not baz because we pick the first one we encounter in the Splits.
|
||||
LoadBalancer: structs.LoadBalancer{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: structs.RingHashConfig{
|
||||
MaximumRingSize: 101,
|
||||
},
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
SourceAddress: true,
|
||||
LoadBalancer: &structs.LoadBalancer{
|
||||
EnvoyLBConfig: &structs.EnvoyLBConfig{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: &structs.RingHashConfig{
|
||||
MaximumRingSize: 101,
|
||||
},
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
SourceIP: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2357,10 +2375,12 @@ func testcase_LBConfig() compileTestCase {
|
|||
ConnectTimeout: 5 * time.Second,
|
||||
Target: "foo.default.dc1",
|
||||
},
|
||||
LoadBalancer: structs.LoadBalancer{
|
||||
Policy: "least_request",
|
||||
LeastRequestConfig: structs.LeastRequestConfig{
|
||||
ChoiceCount: 3,
|
||||
LoadBalancer: &structs.LoadBalancer{
|
||||
EnvoyLBConfig: &structs.EnvoyLBConfig{
|
||||
Policy: "least_request",
|
||||
LeastRequestConfig: &structs.LeastRequestConfig{
|
||||
ChoiceCount: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2372,14 +2392,16 @@ func testcase_LBConfig() compileTestCase {
|
|||
ConnectTimeout: 5 * time.Second,
|
||||
Target: "bar.default.dc1",
|
||||
},
|
||||
LoadBalancer: structs.LoadBalancer{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: structs.RingHashConfig{
|
||||
MaximumRingSize: 101,
|
||||
},
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
SourceAddress: true,
|
||||
LoadBalancer: &structs.LoadBalancer{
|
||||
EnvoyLBConfig: &structs.EnvoyLBConfig{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: &structs.RingHashConfig{
|
||||
MaximumRingSize: 101,
|
||||
},
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
SourceIP: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2392,13 +2414,19 @@ func testcase_LBConfig() compileTestCase {
|
|||
ConnectTimeout: 5 * time.Second,
|
||||
Target: "baz.default.dc1",
|
||||
},
|
||||
LoadBalancer: structs.LoadBalancer{
|
||||
Policy: "maglev",
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
Field: "cookie",
|
||||
FieldMatchValue: "chocolate-chip",
|
||||
Terminal: true,
|
||||
LoadBalancer: &structs.LoadBalancer{
|
||||
EnvoyLBConfig: &structs.EnvoyLBConfig{
|
||||
Policy: "maglev",
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
Field: "cookie",
|
||||
FieldValue: "chocolate-chip",
|
||||
CookieConfig: &structs.CookieConfig{
|
||||
TTL: 2 * time.Minute,
|
||||
Path: "/bowl",
|
||||
},
|
||||
Terminal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1274,25 +1274,27 @@ func setupTestVariationConfigEntriesAndSnapshot(
|
|||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "db",
|
||||
LoadBalancer: structs.LoadBalancer{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: structs.RingHashConfig{
|
||||
MinimumRingSize: 20,
|
||||
MaximumRingSize: 30,
|
||||
},
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
Field: "cookie",
|
||||
FieldMatchValue: "chocolate-chip",
|
||||
Terminal: true,
|
||||
LoadBalancer: &structs.LoadBalancer{
|
||||
EnvoyLBConfig: &structs.EnvoyLBConfig{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: &structs.RingHashConfig{
|
||||
MinimumRingSize: 20,
|
||||
MaximumRingSize: 30,
|
||||
},
|
||||
{
|
||||
Field: "header",
|
||||
FieldMatchValue: "x-user-id",
|
||||
},
|
||||
{
|
||||
SourceAddress: true,
|
||||
Terminal: true,
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
Field: "cookie",
|
||||
FieldValue: "chocolate-chip",
|
||||
Terminal: true,
|
||||
},
|
||||
{
|
||||
Field: "header",
|
||||
FieldValue: "x-user-id",
|
||||
},
|
||||
{
|
||||
SourceIP: true,
|
||||
Terminal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -3,6 +3,7 @@ package structs
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"math"
|
||||
"regexp"
|
||||
"sort"
|
||||
|
@ -10,12 +11,29 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
envoy "github.com/envoyproxy/go-control-plane/envoy/api/v2"
|
||||
envoyroute "github.com/envoyproxy/go-control-plane/envoy/api/v2/route"
|
||||
"github.com/golang/protobuf/ptypes/wrappers"
|
||||
"github.com/hashicorp/consul/acl"
|
||||
"github.com/hashicorp/consul/agent/cache"
|
||||
"github.com/hashicorp/consul/lib"
|
||||
"github.com/mitchellh/hashstructure"
|
||||
)
|
||||
|
||||
const (
|
||||
// Names of Envoy's LB policies
|
||||
LBPolicyMaglev = "maglev"
|
||||
LBPolicyRingHash = "ring_hash"
|
||||
LBPolicyRandom = "random"
|
||||
LBPolicyLeastRequest = "least_request"
|
||||
LBPolicyRoundRobin = "round_robin"
|
||||
|
||||
// Names of Envoy's LB policies
|
||||
HashPolicyCookie = "cookie"
|
||||
HashPolicyHeader = "header"
|
||||
HashPolicyQueryParam = "query_parameter"
|
||||
)
|
||||
|
||||
// ServiceRouterConfigEntry defines L7 (e.g. http) routing rules for a named
|
||||
// service exposed in Connect.
|
||||
//
|
||||
|
@ -641,7 +659,7 @@ type ServiceResolverConfigEntry struct {
|
|||
|
||||
// LoadBalancer determines the load balancing policy and configuration for services
|
||||
// issuing requests to this upstream service.
|
||||
LoadBalancer LoadBalancer `json:",omitempty" alias:"load_balancer"`
|
||||
LoadBalancer *LoadBalancer `json:",omitempty" alias:"load_balancer"`
|
||||
|
||||
EnterpriseMeta `hcl:",squash" mapstructure:",squash"`
|
||||
RaftIndex
|
||||
|
@ -811,53 +829,60 @@ func (e *ServiceResolverConfigEntry) Validate() error {
|
|||
return fmt.Errorf("Bad ConnectTimeout '%s', must be >= 0", e.ConnectTimeout)
|
||||
}
|
||||
|
||||
validPolicies := map[string]bool{
|
||||
"": true,
|
||||
"random": true,
|
||||
"round_robin": true,
|
||||
"least_request": true,
|
||||
"ring_hash": true,
|
||||
"maglev": true,
|
||||
}
|
||||
if ok := validPolicies[e.LoadBalancer.Policy]; !ok {
|
||||
return fmt.Errorf("Bad LoadBalancer policy: %q is not supported", e.LoadBalancer.Policy)
|
||||
}
|
||||
if e.LoadBalancer != nil && e.LoadBalancer.EnvoyLBConfig != nil {
|
||||
ec := e.LoadBalancer.EnvoyLBConfig
|
||||
|
||||
if e.LoadBalancer.Policy != "ring_hash" && e.LoadBalancer.RingHashConfig != (RingHashConfig{}) {
|
||||
return fmt.Errorf("Bad LoadBalancer configuration. "+
|
||||
"RingHashConfig specified for incompatible load balancing policy %q", e.LoadBalancer.Policy)
|
||||
}
|
||||
if e.LoadBalancer.Policy != "least_request" && e.LoadBalancer.LeastRequestConfig != (LeastRequestConfig{}) {
|
||||
return fmt.Errorf("Bad LoadBalancer configuration. "+
|
||||
"LeastRequestConfig specified for incompatible load balancing policy %q", e.LoadBalancer.Policy)
|
||||
}
|
||||
if !e.LoadBalancer.IsHashBased() && len(e.LoadBalancer.HashPolicies) > 0 {
|
||||
return fmt.Errorf("Bad LoadBalancer configuration: "+
|
||||
"HashPolicies specified for non-hash-based Policy: %q", e.LoadBalancer.Policy)
|
||||
}
|
||||
validPolicies := map[string]bool{
|
||||
"": true,
|
||||
LBPolicyRandom: true,
|
||||
LBPolicyRoundRobin: true,
|
||||
LBPolicyLeastRequest: true,
|
||||
LBPolicyRingHash: true,
|
||||
LBPolicyMaglev: true,
|
||||
}
|
||||
if ok := validPolicies[ec.Policy]; !ok {
|
||||
return fmt.Errorf("Bad LoadBalancer policy: %q is not supported", ec.Policy)
|
||||
}
|
||||
|
||||
validFields := map[string]bool{
|
||||
"header": true,
|
||||
"cookie": true,
|
||||
"query_parameter": true,
|
||||
}
|
||||
for i, hp := range e.LoadBalancer.HashPolicies {
|
||||
if ok := validFields[hp.Field]; hp.Field != "" && !ok {
|
||||
return fmt.Errorf("Bad LoadBalancer HashPolicy[%d]: %q is not a supported field", i, hp.Field)
|
||||
if ec.Policy != LBPolicyRingHash && ec.RingHashConfig != nil {
|
||||
return fmt.Errorf("Bad LoadBalancer configuration. "+
|
||||
"RingHashConfig specified for incompatible load balancing policy %q", ec.Policy)
|
||||
}
|
||||
if hp.SourceAddress && hp.Field != "" {
|
||||
return fmt.Errorf("Bad LoadBalancer HashPolicy[%d]: "+
|
||||
"A single hash policy cannot hash both a source address and a %q", i, hp.Field)
|
||||
if ec.Policy != LBPolicyLeastRequest && ec.LeastRequestConfig != nil {
|
||||
return fmt.Errorf("Bad LoadBalancer configuration. "+
|
||||
"LeastRequestConfig specified for incompatible load balancing policy %q", ec.Policy)
|
||||
}
|
||||
if hp.SourceAddress && hp.FieldMatchValue != "" {
|
||||
return fmt.Errorf("Bad LoadBalancer HashPolicy[%d]: "+
|
||||
"A FieldMatchValue cannot be specified when hashing SourceAddress", i)
|
||||
if !ec.IsHashBased() && len(ec.HashPolicies) > 0 {
|
||||
return fmt.Errorf("Bad LoadBalancer configuration: "+
|
||||
"HashPolicies specified for non-hash-based Policy: %q", ec.Policy)
|
||||
}
|
||||
if hp.Field != "" && hp.FieldMatchValue == "" {
|
||||
return fmt.Errorf("Bad LoadBalancer HashPolicy[%d]: Field %q was specified without a FieldMatchValue", i, hp.Field)
|
||||
|
||||
validFields := map[string]bool{
|
||||
HashPolicyHeader: true,
|
||||
HashPolicyCookie: true,
|
||||
HashPolicyQueryParam: true,
|
||||
}
|
||||
if hp.FieldMatchValue != "" && hp.Field == "" {
|
||||
return fmt.Errorf("Bad LoadBalancer HashPolicy[%d]: FieldMatchValue requires a Field to apply to", i)
|
||||
for i, hp := range ec.HashPolicies {
|
||||
if ok := validFields[hp.Field]; hp.Field != "" && !ok {
|
||||
return fmt.Errorf("Bad LoadBalancer HashPolicy[%d]: %q is not a supported field", i, hp.Field)
|
||||
}
|
||||
if hp.SourceIP && hp.Field != "" {
|
||||
return fmt.Errorf("Bad LoadBalancer HashPolicy[%d]: "+
|
||||
"A single hash policy cannot hash both a source address and a %q", i, hp.Field)
|
||||
}
|
||||
if hp.SourceIP && hp.FieldValue != "" {
|
||||
return fmt.Errorf("Bad LoadBalancer HashPolicy[%d]: "+
|
||||
"A FieldValue cannot be specified when hashing SourceIP", i)
|
||||
}
|
||||
if hp.Field != "" && hp.FieldValue == "" {
|
||||
return fmt.Errorf("Bad LoadBalancer HashPolicy[%d]: Field %q was specified without a FieldValue", i, hp.Field)
|
||||
}
|
||||
if hp.FieldValue != "" && hp.Field == "" {
|
||||
return fmt.Errorf("Bad LoadBalancer HashPolicy[%d]: FieldValue requires a Field to apply to", i)
|
||||
}
|
||||
if hp.CookieConfig != nil && hp.Field != HashPolicyCookie {
|
||||
return fmt.Errorf("Bad LoadBalancer HashPolicy[%d]: cookie_config provided for %q", i, hp.Field)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1000,14 +1025,22 @@ type ServiceResolverFailover struct {
|
|||
// LoadBalancer determines the load balancing policy and configuration for services
|
||||
// issuing requests to this upstream service.
|
||||
type LoadBalancer struct {
|
||||
// EnvoyLBConfig contains Envoy-specific load balancing configuration for this upstream
|
||||
EnvoyLBConfig *EnvoyLBConfig `json:",omitempty" alias:"envoy_lb_config"`
|
||||
|
||||
// OpaqueConfig contains load balancing configuration opaque to Consul for 3rd party proxies
|
||||
OpaqueConfig string `json:",omitempty" alias:"opaque_config"`
|
||||
}
|
||||
|
||||
type EnvoyLBConfig struct {
|
||||
// Policy is the load balancing policy used to select a host
|
||||
Policy string `json:",omitempty"`
|
||||
|
||||
// RingHashConfig contains configuration for the "ring_hash" policy type
|
||||
RingHashConfig RingHashConfig `json:",omitempty" alias:"ring_hash_config"`
|
||||
RingHashConfig *RingHashConfig `json:",omitempty" alias:"ring_hash_config"`
|
||||
|
||||
// LeastRequestConfig contains configuration for the "least_request" policy type
|
||||
LeastRequestConfig LeastRequestConfig `json:",omitempty" alias:"least_request_config"`
|
||||
LeastRequestConfig *LeastRequestConfig `json:",omitempty" alias:"least_request_config"`
|
||||
|
||||
// HashPolicies is a list of hash policies to use for hashing load balancing algorithms.
|
||||
// Hash policies are evaluated individually and combined such that identical lists
|
||||
|
@ -1017,15 +1050,6 @@ type LoadBalancer struct {
|
|||
HashPolicies []HashPolicy `json:",omitempty" alias:"hash_policies"`
|
||||
}
|
||||
|
||||
func (l LoadBalancer) IsHashBased() bool {
|
||||
switch l.Policy {
|
||||
case "maglev", "ring_hash":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// RingHashConfig contains configuration for the "ring_hash" policy type
|
||||
type RingHashConfig struct {
|
||||
// MinimumRingSize determines the minimum number of entries in the hash ring
|
||||
|
@ -1041,25 +1065,24 @@ type LeastRequestConfig struct {
|
|||
ChoiceCount uint32 `json:",omitempty" alias:"choice_count"`
|
||||
}
|
||||
|
||||
// HashPolicy is a list of hash policies to use for hashing load balancing algorithms.
|
||||
// Hash policies are evaluated individually and combined such that identical lists
|
||||
// result in the same hash.
|
||||
// If no hash policies are present, or none are successfully evaluated,
|
||||
// then a random backend host will be selected.
|
||||
// HashPolicy defines which attributes will be hashed by hash-based LB algorithms
|
||||
type HashPolicy struct {
|
||||
// Field is the attribute type to hash on.
|
||||
// Must be one of "header","cookie", or "query_parameter".
|
||||
// Cannot be specified along with SourceIP.
|
||||
Field string `json:",omitempty"`
|
||||
|
||||
// FieldMatchValue is the value to hash.
|
||||
// FieldValue is the value to hash.
|
||||
// ie. header name, cookie name, URL query parameter name
|
||||
// Cannot be specified along with SourceIP.
|
||||
FieldMatchValue string `json:",omitempty" alias:"field_value"`
|
||||
FieldValue string `json:",omitempty" alias:"field_value"`
|
||||
|
||||
// SourceAddress determines whether the hash should be of the source IP rather than of a field and field value.
|
||||
// Cannot be specified along with Field or FieldMatchValue.
|
||||
SourceAddress bool `json:",omitempty" alias:"source_address"`
|
||||
// CookieConfig contains configuration for the "cookie" hash policy type.
|
||||
CookieConfig *CookieConfig `json:",omitempty" alias:"cookie_config"`
|
||||
|
||||
// SourceIP determines whether the hash should be of the source IP rather than of a field and field value.
|
||||
// Cannot be specified along with Field or FieldValue.
|
||||
SourceIP bool `json:",omitempty" alias:"source_ip"`
|
||||
|
||||
// Terminal will short circuit the computation of the hash when multiple hash policies are present.
|
||||
// If a hash is computed when a Terminal policy is evaluated,
|
||||
|
@ -1067,6 +1090,134 @@ type HashPolicy struct {
|
|||
Terminal bool `json:",omitempty"`
|
||||
}
|
||||
|
||||
// CookieConfig contains configuration for the "cookie" hash policy type.
|
||||
// This is specified to have Envoy generate a cookie for a client on its first request.
|
||||
type CookieConfig struct {
|
||||
// TTL for generated cookies
|
||||
TTL time.Duration `json:",omitempty"`
|
||||
|
||||
// The path to set for the cookie
|
||||
Path string `json:",omitempty"`
|
||||
}
|
||||
|
||||
func (ec *EnvoyLBConfig) IsHashBased() bool {
|
||||
if ec == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
switch ec.Policy {
|
||||
case LBPolicyMaglev, LBPolicyRingHash:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (ec *EnvoyLBConfig) InjectToCluster(c *envoy.Cluster) error {
|
||||
if ec == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch ec.Policy {
|
||||
case "":
|
||||
return nil
|
||||
case LBPolicyLeastRequest:
|
||||
c.LbPolicy = envoy.Cluster_LEAST_REQUEST
|
||||
|
||||
if ec.LeastRequestConfig != nil {
|
||||
c.LbConfig = &envoy.Cluster_LeastRequestLbConfig_{
|
||||
LeastRequestLbConfig: &envoy.Cluster_LeastRequestLbConfig{
|
||||
ChoiceCount: &wrappers.UInt32Value{Value: ec.LeastRequestConfig.ChoiceCount},
|
||||
},
|
||||
}
|
||||
}
|
||||
case LBPolicyRoundRobin:
|
||||
c.LbPolicy = envoy.Cluster_ROUND_ROBIN
|
||||
|
||||
case LBPolicyRandom:
|
||||
c.LbPolicy = envoy.Cluster_RANDOM
|
||||
|
||||
case LBPolicyRingHash:
|
||||
c.LbPolicy = envoy.Cluster_RING_HASH
|
||||
|
||||
if ec.RingHashConfig != nil {
|
||||
c.LbConfig = &envoy.Cluster_RingHashLbConfig_{
|
||||
RingHashLbConfig: &envoy.Cluster_RingHashLbConfig{
|
||||
MinimumRingSize: &wrappers.UInt64Value{Value: ec.RingHashConfig.MinimumRingSize},
|
||||
MaximumRingSize: &wrappers.UInt64Value{Value: ec.RingHashConfig.MaximumRingSize},
|
||||
},
|
||||
}
|
||||
}
|
||||
case LBPolicyMaglev:
|
||||
c.LbPolicy = envoy.Cluster_MAGLEV
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unsupported load balancer policy %q for cluster %q", ec.Policy, c.Name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ec *EnvoyLBConfig) InjectToRouteAction(action *envoyroute.RouteAction) error {
|
||||
if ec == nil || !ec.IsHashBased() {
|
||||
return nil
|
||||
}
|
||||
|
||||
result := make([]*envoyroute.RouteAction_HashPolicy, 0, len(ec.HashPolicies))
|
||||
for _, policy := range ec.HashPolicies {
|
||||
if policy.SourceIP {
|
||||
result = append(result, &envoyroute.RouteAction_HashPolicy{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_ConnectionProperties_{
|
||||
ConnectionProperties: &envoyroute.RouteAction_HashPolicy_ConnectionProperties{
|
||||
SourceIp: true,
|
||||
},
|
||||
},
|
||||
Terminal: policy.Terminal,
|
||||
})
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
switch policy.Field {
|
||||
case HashPolicyHeader:
|
||||
result = append(result, &envoyroute.RouteAction_HashPolicy{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_Header_{
|
||||
Header: &envoyroute.RouteAction_HashPolicy_Header{
|
||||
HeaderName: policy.FieldValue,
|
||||
},
|
||||
},
|
||||
Terminal: policy.Terminal,
|
||||
})
|
||||
case HashPolicyCookie:
|
||||
cookie := envoyroute.RouteAction_HashPolicy_Cookie{
|
||||
Name: policy.FieldValue,
|
||||
}
|
||||
if policy.CookieConfig != nil {
|
||||
cookie.Ttl = ptypes.DurationProto(policy.CookieConfig.TTL)
|
||||
cookie.Path = policy.CookieConfig.Path
|
||||
}
|
||||
result = append(result, &envoyroute.RouteAction_HashPolicy{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_Cookie_{
|
||||
Cookie: &cookie,
|
||||
},
|
||||
Terminal: policy.Terminal,
|
||||
})
|
||||
case HashPolicyQueryParam:
|
||||
result = append(result, &envoyroute.RouteAction_HashPolicy{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_QueryParameter_{
|
||||
QueryParameter: &envoyroute.RouteAction_HashPolicy_QueryParameter{
|
||||
Name: policy.FieldValue,
|
||||
},
|
||||
},
|
||||
Terminal: policy.Terminal,
|
||||
})
|
||||
default:
|
||||
return fmt.Errorf("unsupported load balancer hash policy field: %v", policy.Field)
|
||||
}
|
||||
}
|
||||
action.HashPolicy = result
|
||||
return nil
|
||||
}
|
||||
|
||||
type discoveryChainConfigEntry interface {
|
||||
ConfigEntry
|
||||
// ListRelatedServices returns a list of other names of services referenced
|
||||
|
|
|
@ -3,10 +3,14 @@ package structs
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
envoy "github.com/envoyproxy/go-control-plane/envoy/api/v2"
|
||||
envoyroute "github.com/envoyproxy/go-control-plane/envoy/api/v2/route"
|
||||
"github.com/golang/protobuf/ptypes/wrappers"
|
||||
"github.com/hashicorp/consul/acl"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -552,25 +556,31 @@ func TestServiceResolverConfigEntry_LoadBalancer(t *testing.T) {
|
|||
{
|
||||
name: "empty policy is valid",
|
||||
entry: &ServiceResolverConfigEntry{
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: LoadBalancer{Policy: ""},
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: &LoadBalancer{
|
||||
EnvoyLBConfig: &EnvoyLBConfig{Policy: ""},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "supported policy",
|
||||
entry: &ServiceResolverConfigEntry{
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: LoadBalancer{Policy: "random"},
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: &LoadBalancer{
|
||||
EnvoyLBConfig: &EnvoyLBConfig{Policy: LBPolicyRandom},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "unsupported policy",
|
||||
entry: &ServiceResolverConfigEntry{
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: LoadBalancer{Policy: "fake-policy"},
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: &LoadBalancer{
|
||||
EnvoyLBConfig: &EnvoyLBConfig{Policy: "fake-policy"},
|
||||
},
|
||||
},
|
||||
validateErr: `"fake-policy" is not supported`,
|
||||
},
|
||||
|
@ -579,9 +589,11 @@ func TestServiceResolverConfigEntry_LoadBalancer(t *testing.T) {
|
|||
entry: &ServiceResolverConfigEntry{
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: LoadBalancer{
|
||||
Policy: "ring_hash",
|
||||
LeastRequestConfig: LeastRequestConfig{ChoiceCount: 2},
|
||||
LoadBalancer: &LoadBalancer{
|
||||
EnvoyLBConfig: &EnvoyLBConfig{
|
||||
Policy: LBPolicyRingHash,
|
||||
LeastRequestConfig: &LeastRequestConfig{ChoiceCount: 10},
|
||||
},
|
||||
},
|
||||
},
|
||||
validateErr: `LeastRequestConfig specified for incompatible load balancing policy`,
|
||||
|
@ -591,9 +603,11 @@ func TestServiceResolverConfigEntry_LoadBalancer(t *testing.T) {
|
|||
entry: &ServiceResolverConfigEntry{
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: LoadBalancer{
|
||||
Policy: "least_request",
|
||||
RingHashConfig: RingHashConfig{MinimumRingSize: 1024},
|
||||
LoadBalancer: &LoadBalancer{
|
||||
EnvoyLBConfig: &EnvoyLBConfig{
|
||||
Policy: LBPolicyLeastRequest,
|
||||
RingHashConfig: &RingHashConfig{MinimumRingSize: 1024},
|
||||
},
|
||||
},
|
||||
},
|
||||
validateErr: `RingHashConfig specified for incompatible load balancing policy`,
|
||||
|
@ -603,9 +617,11 @@ func TestServiceResolverConfigEntry_LoadBalancer(t *testing.T) {
|
|||
entry: &ServiceResolverConfigEntry{
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: LoadBalancer{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: RingHashConfig{MinimumRingSize: 1024},
|
||||
LoadBalancer: &LoadBalancer{
|
||||
EnvoyLBConfig: &EnvoyLBConfig{
|
||||
Policy: LBPolicyRingHash,
|
||||
RingHashConfig: &RingHashConfig{MinimumRingSize: 1024},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -614,9 +630,11 @@ func TestServiceResolverConfigEntry_LoadBalancer(t *testing.T) {
|
|||
entry: &ServiceResolverConfigEntry{
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: LoadBalancer{
|
||||
Policy: "least_request",
|
||||
LeastRequestConfig: LeastRequestConfig{ChoiceCount: 2},
|
||||
LoadBalancer: &LoadBalancer{
|
||||
EnvoyLBConfig: &EnvoyLBConfig{
|
||||
Policy: LBPolicyLeastRequest,
|
||||
LeastRequestConfig: &LeastRequestConfig{ChoiceCount: 2},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -625,12 +643,12 @@ func TestServiceResolverConfigEntry_LoadBalancer(t *testing.T) {
|
|||
entry: &ServiceResolverConfigEntry{
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: LoadBalancer{
|
||||
Policy: "",
|
||||
LoadBalancer: &LoadBalancer{
|
||||
EnvoyLBConfig: &EnvoyLBConfig{Policy: ""},
|
||||
},
|
||||
},
|
||||
check: func(t *testing.T, entry *ServiceResolverConfigEntry) {
|
||||
require.Equal(t, "", entry.LoadBalancer.Policy)
|
||||
require.Equal(t, "", entry.LoadBalancer.EnvoyLBConfig.Policy)
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -638,28 +656,77 @@ func TestServiceResolverConfigEntry_LoadBalancer(t *testing.T) {
|
|||
entry: &ServiceResolverConfigEntry{
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: LoadBalancer{
|
||||
Policy: "",
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
SourceAddress: true,
|
||||
LoadBalancer: &LoadBalancer{
|
||||
EnvoyLBConfig: &EnvoyLBConfig{
|
||||
Policy: "",
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
SourceIP: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
validateErr: `HashPolicies specified for non-hash-based Policy`,
|
||||
},
|
||||
{
|
||||
name: "empty policy with hash policy",
|
||||
entry: &ServiceResolverConfigEntry{
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: &LoadBalancer{
|
||||
EnvoyLBConfig: &EnvoyLBConfig{
|
||||
Policy: LBPolicyMaglev,
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
Field: HashPolicyHeader,
|
||||
FieldValue: "x-user-id",
|
||||
CookieConfig: &CookieConfig{
|
||||
TTL: 10 * time.Second,
|
||||
Path: "/root",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
validateErr: `cookie_config provided for "header"`,
|
||||
},
|
||||
{
|
||||
name: "empty policy with hash policy",
|
||||
entry: &ServiceResolverConfigEntry{
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: &LoadBalancer{
|
||||
EnvoyLBConfig: &EnvoyLBConfig{
|
||||
Policy: LBPolicyMaglev,
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
Field: HashPolicyCookie,
|
||||
FieldValue: "good-cookie",
|
||||
CookieConfig: &CookieConfig{
|
||||
TTL: 10 * time.Second,
|
||||
Path: "/oven",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "supported match field",
|
||||
entry: &ServiceResolverConfigEntry{
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: LoadBalancer{
|
||||
Policy: "maglev",
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
Field: "header",
|
||||
FieldMatchValue: "X-Consul-Token",
|
||||
LoadBalancer: &LoadBalancer{
|
||||
EnvoyLBConfig: &EnvoyLBConfig{
|
||||
Policy: LBPolicyMaglev,
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
Field: "header",
|
||||
FieldValue: "X-Consul-Token",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -670,28 +737,32 @@ func TestServiceResolverConfigEntry_LoadBalancer(t *testing.T) {
|
|||
entry: &ServiceResolverConfigEntry{
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: LoadBalancer{
|
||||
Policy: "maglev",
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
Field: "not-header",
|
||||
LoadBalancer: &LoadBalancer{
|
||||
EnvoyLBConfig: &EnvoyLBConfig{
|
||||
Policy: LBPolicyMaglev,
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
Field: "fake-field",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
validateErr: `"not-header" is not a supported field`,
|
||||
validateErr: `"fake-field" is not a supported field`,
|
||||
},
|
||||
{
|
||||
name: "cannot match on source address and custom field",
|
||||
entry: &ServiceResolverConfigEntry{
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: LoadBalancer{
|
||||
Policy: "maglev",
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
Field: "header",
|
||||
SourceAddress: true,
|
||||
LoadBalancer: &LoadBalancer{
|
||||
EnvoyLBConfig: &EnvoyLBConfig{
|
||||
Policy: LBPolicyMaglev,
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
Field: "header",
|
||||
SourceIP: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -703,67 +774,75 @@ func TestServiceResolverConfigEntry_LoadBalancer(t *testing.T) {
|
|||
entry: &ServiceResolverConfigEntry{
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: LoadBalancer{
|
||||
Policy: "maglev",
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
FieldMatchValue: "X-Consul-Token",
|
||||
SourceAddress: true,
|
||||
LoadBalancer: &LoadBalancer{
|
||||
EnvoyLBConfig: &EnvoyLBConfig{
|
||||
Policy: LBPolicyMaglev,
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
FieldValue: "X-Consul-Token",
|
||||
SourceIP: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
validateErr: `A FieldMatchValue cannot be specified when hashing SourceAddress`,
|
||||
validateErr: `A FieldValue cannot be specified when hashing SourceIP`,
|
||||
},
|
||||
{
|
||||
name: "field without match value",
|
||||
entry: &ServiceResolverConfigEntry{
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: LoadBalancer{
|
||||
Policy: "maglev",
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
Field: "header",
|
||||
LoadBalancer: &LoadBalancer{
|
||||
EnvoyLBConfig: &EnvoyLBConfig{
|
||||
Policy: LBPolicyMaglev,
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
Field: "header",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
validateErr: `Field "header" was specified without a FieldMatchValue`,
|
||||
validateErr: `Field "header" was specified without a FieldValue`,
|
||||
},
|
||||
{
|
||||
name: "field without match value",
|
||||
entry: &ServiceResolverConfigEntry{
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: LoadBalancer{
|
||||
Policy: "maglev",
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
FieldMatchValue: "my-cookie",
|
||||
LoadBalancer: &LoadBalancer{
|
||||
EnvoyLBConfig: &EnvoyLBConfig{
|
||||
Policy: LBPolicyMaglev,
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
FieldValue: "my-cookie",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
validateErr: `FieldMatchValue requires a Field to apply to`,
|
||||
validateErr: `FieldValue requires a Field to apply to`,
|
||||
},
|
||||
{
|
||||
name: "ring hash kitchen sink",
|
||||
entry: &ServiceResolverConfigEntry{
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: LoadBalancer{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: RingHashConfig{MaximumRingSize: 10, MinimumRingSize: 2},
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
Field: "cookie",
|
||||
FieldMatchValue: "my-cookie",
|
||||
},
|
||||
{
|
||||
Field: "header",
|
||||
FieldMatchValue: "alt-header",
|
||||
Terminal: true,
|
||||
LoadBalancer: &LoadBalancer{
|
||||
EnvoyLBConfig: &EnvoyLBConfig{
|
||||
Policy: LBPolicyRingHash,
|
||||
RingHashConfig: &RingHashConfig{MaximumRingSize: 10, MinimumRingSize: 2},
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
Field: "cookie",
|
||||
FieldValue: "my-cookie",
|
||||
},
|
||||
{
|
||||
Field: "header",
|
||||
FieldValue: "alt-header",
|
||||
Terminal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -774,9 +853,11 @@ func TestServiceResolverConfigEntry_LoadBalancer(t *testing.T) {
|
|||
entry: &ServiceResolverConfigEntry{
|
||||
Kind: ServiceResolver,
|
||||
Name: "test",
|
||||
LoadBalancer: LoadBalancer{
|
||||
Policy: "least_request",
|
||||
LeastRequestConfig: LeastRequestConfig{ChoiceCount: 20},
|
||||
LoadBalancer: &LoadBalancer{
|
||||
EnvoyLBConfig: &EnvoyLBConfig{
|
||||
Policy: LBPolicyLeastRequest,
|
||||
LeastRequestConfig: &LeastRequestConfig{ChoiceCount: 20},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1444,3 +1525,267 @@ func TestIsProtocolHTTPLike(t *testing.T) {
|
|||
assert.True(t, IsProtocolHTTPLike("http2"))
|
||||
assert.True(t, IsProtocolHTTPLike("grpc"))
|
||||
}
|
||||
|
||||
func TestEnvoyLBConfig_InjectToRouteAction(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
lb *EnvoyLBConfig
|
||||
expected envoyroute.RouteAction
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
lb: &EnvoyLBConfig{
|
||||
Policy: "",
|
||||
},
|
||||
// we only modify route actions for hash-based LB policies
|
||||
expected: envoyroute.RouteAction{},
|
||||
},
|
||||
{
|
||||
name: "least request",
|
||||
lb: &EnvoyLBConfig{
|
||||
Policy: LBPolicyLeastRequest,
|
||||
LeastRequestConfig: &LeastRequestConfig{
|
||||
ChoiceCount: 3,
|
||||
},
|
||||
},
|
||||
// we only modify route actions for hash-based LB policies
|
||||
expected: envoyroute.RouteAction{},
|
||||
},
|
||||
{
|
||||
name: "headers",
|
||||
lb: &EnvoyLBConfig{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: &RingHashConfig{
|
||||
MinimumRingSize: 3,
|
||||
MaximumRingSize: 7,
|
||||
},
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
Field: HashPolicyHeader,
|
||||
FieldValue: "x-route-key",
|
||||
Terminal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: envoyroute.RouteAction{
|
||||
HashPolicy: []*envoyroute.RouteAction_HashPolicy{
|
||||
{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_Header_{
|
||||
Header: &envoyroute.RouteAction_HashPolicy_Header{
|
||||
HeaderName: "x-route-key",
|
||||
},
|
||||
},
|
||||
Terminal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "cookies",
|
||||
lb: &EnvoyLBConfig{
|
||||
Policy: LBPolicyMaglev,
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
Field: HashPolicyCookie,
|
||||
FieldValue: "red-velvet",
|
||||
Terminal: true,
|
||||
},
|
||||
{
|
||||
Field: HashPolicyCookie,
|
||||
FieldValue: "oatmeal",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: envoyroute.RouteAction{
|
||||
HashPolicy: []*envoyroute.RouteAction_HashPolicy{
|
||||
{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_Cookie_{
|
||||
Cookie: &envoyroute.RouteAction_HashPolicy_Cookie{
|
||||
Name: "red-velvet",
|
||||
},
|
||||
},
|
||||
Terminal: true,
|
||||
},
|
||||
{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_Cookie_{
|
||||
Cookie: &envoyroute.RouteAction_HashPolicy_Cookie{
|
||||
Name: "oatmeal",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "source addr",
|
||||
lb: &EnvoyLBConfig{
|
||||
Policy: LBPolicyMaglev,
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
SourceIP: true,
|
||||
Terminal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: envoyroute.RouteAction{
|
||||
HashPolicy: []*envoyroute.RouteAction_HashPolicy{
|
||||
{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_ConnectionProperties_{
|
||||
ConnectionProperties: &envoyroute.RouteAction_HashPolicy_ConnectionProperties{
|
||||
SourceIp: true,
|
||||
},
|
||||
},
|
||||
Terminal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "kitchen sink",
|
||||
lb: &EnvoyLBConfig{
|
||||
Policy: LBPolicyMaglev,
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
SourceIP: true,
|
||||
Terminal: true,
|
||||
},
|
||||
{
|
||||
Field: HashPolicyCookie,
|
||||
FieldValue: "oatmeal",
|
||||
CookieConfig: &CookieConfig{
|
||||
TTL: 10 * time.Second,
|
||||
Path: "/oven",
|
||||
},
|
||||
},
|
||||
{
|
||||
Field: HashPolicyHeader,
|
||||
FieldValue: "special-header",
|
||||
Terminal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: envoyroute.RouteAction{
|
||||
HashPolicy: []*envoyroute.RouteAction_HashPolicy{
|
||||
{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_ConnectionProperties_{
|
||||
ConnectionProperties: &envoyroute.RouteAction_HashPolicy_ConnectionProperties{
|
||||
SourceIp: true,
|
||||
},
|
||||
},
|
||||
Terminal: true,
|
||||
},
|
||||
{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_Cookie_{
|
||||
Cookie: &envoyroute.RouteAction_HashPolicy_Cookie{
|
||||
Name: "oatmeal",
|
||||
Ttl: ptypes.DurationProto(10 * time.Second),
|
||||
Path: "/oven",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_Header_{
|
||||
Header: &envoyroute.RouteAction_HashPolicy_Header{
|
||||
HeaderName: "special-header",
|
||||
},
|
||||
},
|
||||
Terminal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var ra envoyroute.RouteAction
|
||||
err := tc.lb.InjectToRouteAction(&ra)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, &tc.expected, &ra)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnvoyLBConfig_InjectToCluster(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
lb *EnvoyLBConfig
|
||||
expected envoy.Cluster
|
||||
}{
|
||||
{
|
||||
name: "skip empty",
|
||||
lb: &EnvoyLBConfig{
|
||||
Policy: "",
|
||||
},
|
||||
expected: envoy.Cluster{},
|
||||
},
|
||||
{
|
||||
name: "round robin",
|
||||
lb: &EnvoyLBConfig{
|
||||
Policy: LBPolicyRoundRobin,
|
||||
},
|
||||
expected: envoy.Cluster{LbPolicy: envoy.Cluster_ROUND_ROBIN},
|
||||
},
|
||||
{
|
||||
name: "random",
|
||||
lb: &EnvoyLBConfig{
|
||||
Policy: LBPolicyRandom,
|
||||
},
|
||||
expected: envoy.Cluster{LbPolicy: envoy.Cluster_RANDOM},
|
||||
},
|
||||
{
|
||||
name: "maglev",
|
||||
lb: &EnvoyLBConfig{
|
||||
Policy: LBPolicyMaglev,
|
||||
},
|
||||
expected: envoy.Cluster{LbPolicy: envoy.Cluster_MAGLEV},
|
||||
},
|
||||
{
|
||||
name: "ring_hash",
|
||||
lb: &EnvoyLBConfig{
|
||||
Policy: LBPolicyRingHash,
|
||||
RingHashConfig: &RingHashConfig{
|
||||
MinimumRingSize: 3,
|
||||
MaximumRingSize: 7,
|
||||
},
|
||||
},
|
||||
expected: envoy.Cluster{
|
||||
LbPolicy: envoy.Cluster_RING_HASH,
|
||||
LbConfig: &envoy.Cluster_RingHashLbConfig_{
|
||||
RingHashLbConfig: &envoy.Cluster_RingHashLbConfig{
|
||||
MinimumRingSize: &wrappers.UInt64Value{Value: 3},
|
||||
MaximumRingSize: &wrappers.UInt64Value{Value: 7},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "least_request",
|
||||
lb: &EnvoyLBConfig{
|
||||
Policy: "least_request",
|
||||
LeastRequestConfig: &LeastRequestConfig{
|
||||
ChoiceCount: 3,
|
||||
},
|
||||
},
|
||||
expected: envoy.Cluster{
|
||||
LbPolicy: envoy.Cluster_LEAST_REQUEST,
|
||||
LbConfig: &envoy.Cluster_LeastRequestLbConfig_{
|
||||
LeastRequestLbConfig: &envoy.Cluster_LeastRequestLbConfig{
|
||||
ChoiceCount: &wrappers.UInt32Value{Value: 3},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var c envoy.Cluster
|
||||
err := tc.lb.InjectToCluster(&c)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, tc.expected, c)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ type DiscoveryGraphNode struct {
|
|||
Resolver *DiscoveryResolver `json:",omitempty"`
|
||||
|
||||
// shared by Type==resolver || Type==splitter
|
||||
LoadBalancer LoadBalancer `json:",omitempty"`
|
||||
LoadBalancer *LoadBalancer `json:",omitempty"`
|
||||
}
|
||||
|
||||
func (s *DiscoveryGraphNode) IsRouter() bool {
|
||||
|
|
|
@ -16,7 +16,6 @@ import (
|
|||
"github.com/golang/protobuf/proto"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"github.com/golang/protobuf/ptypes/any"
|
||||
"github.com/golang/protobuf/ptypes/wrappers"
|
||||
"github.com/hashicorp/consul/agent/connect"
|
||||
"github.com/hashicorp/consul/agent/proxycfg"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
|
@ -206,13 +205,14 @@ func (s *Server) makeGatewayServiceClusters(cfgSnap *proxycfg.ConfigSnapshot) ([
|
|||
clusterName := connect.ServiceSNI(svc.Name, "", svc.NamespaceOrDefault(), cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain)
|
||||
resolver, hasResolver := resolvers[svc]
|
||||
|
||||
var lb structs.LoadBalancer
|
||||
var loadBalancer *structs.EnvoyLBConfig
|
||||
|
||||
if !hasResolver {
|
||||
if hasResolver && resolver.LoadBalancer != nil {
|
||||
loadBalancer = resolver.LoadBalancer.EnvoyLBConfig
|
||||
|
||||
} else {
|
||||
// Use a zero value resolver with no timeout and no subsets
|
||||
resolver = &structs.ServiceResolverConfigEntry{}
|
||||
} else {
|
||||
lb = resolver.LoadBalancer
|
||||
}
|
||||
|
||||
// When making service clusters we only pass endpoints with hostnames if the kind is a terminating gateway
|
||||
|
@ -232,16 +232,14 @@ func (s *Server) makeGatewayServiceClusters(cfgSnap *proxycfg.ConfigSnapshot) ([
|
|||
case structs.ServiceKindTerminatingGateway:
|
||||
injectTerminatingGatewayTLSContext(cfgSnap, cluster, svc)
|
||||
|
||||
err := injectLBToCluster(lb, cluster)
|
||||
if err != nil {
|
||||
if err := loadBalancer.InjectToCluster(cluster); err != nil {
|
||||
return nil, fmt.Errorf("failed to apply load balancer configuration to cluster %q: %v", clusterName, err)
|
||||
}
|
||||
case structs.ServiceKindMeshGateway:
|
||||
// We can't apply hash based LB config to mesh gateways because they rely on inspecting HTTP attributes
|
||||
// and mesh gateways do not decrypt traffic
|
||||
if !lb.IsHashBased() {
|
||||
err := injectLBToCluster(lb, cluster)
|
||||
if err != nil {
|
||||
if !loadBalancer.IsHashBased() {
|
||||
if err := loadBalancer.InjectToCluster(cluster); err != nil {
|
||||
return nil, fmt.Errorf("failed to apply load balancer configuration to cluster %q: %v", clusterName, err)
|
||||
}
|
||||
}
|
||||
|
@ -267,16 +265,15 @@ func (s *Server) makeGatewayServiceClusters(cfgSnap *proxycfg.ConfigSnapshot) ([
|
|||
case structs.ServiceKindTerminatingGateway:
|
||||
injectTerminatingGatewayTLSContext(cfgSnap, cluster, svc)
|
||||
|
||||
err := injectLBToCluster(lb, cluster)
|
||||
if err != nil {
|
||||
if err := loadBalancer.InjectToCluster(cluster); err != nil {
|
||||
return nil, fmt.Errorf("failed to apply load balancer configuration to cluster %q: %v", clusterName, err)
|
||||
}
|
||||
|
||||
case structs.ServiceKindMeshGateway:
|
||||
// We can't apply hash based LB config to mesh gateways because they rely on inspecting HTTP attributes
|
||||
// and mesh gateways do not decrypt traffic
|
||||
if !lb.IsHashBased() {
|
||||
err := injectLBToCluster(lb, cluster)
|
||||
if err != nil {
|
||||
if !loadBalancer.IsHashBased() {
|
||||
if err := loadBalancer.InjectToCluster(cluster); err != nil {
|
||||
return nil, fmt.Errorf("failed to apply load balancer configuration to cluster %q: %v", clusterName, err)
|
||||
}
|
||||
}
|
||||
|
@ -516,8 +513,12 @@ func (s *Server) makeUpstreamClustersForDiscoveryChain(
|
|||
OutlierDetection: cfg.PassiveHealthCheck.AsOutlierDetection(),
|
||||
}
|
||||
|
||||
if err := injectLBToCluster(node.LoadBalancer, c); err != nil {
|
||||
return nil, fmt.Errorf("failed to apply load balancer configuration to cluster %q: %v", sni, err)
|
||||
var lb *structs.EnvoyLBConfig
|
||||
if node.LoadBalancer != nil {
|
||||
lb = node.LoadBalancer.EnvoyLBConfig
|
||||
}
|
||||
if err := lb.InjectToCluster(c); err != nil {
|
||||
return nil, fmt.Errorf("failed to apply load balancer configuration to cluster %q: %v", clusterName, err)
|
||||
}
|
||||
|
||||
proto := cfg.Protocol
|
||||
|
@ -557,37 +558,6 @@ func (s *Server) makeUpstreamClustersForDiscoveryChain(
|
|||
return out, nil
|
||||
}
|
||||
|
||||
func injectLBToCluster(l structs.LoadBalancer, c *envoy.Cluster) error {
|
||||
switch l.Policy {
|
||||
case "":
|
||||
return nil
|
||||
case "least_request":
|
||||
c.LbPolicy = envoy.Cluster_LEAST_REQUEST
|
||||
c.LbConfig = &envoy.Cluster_LeastRequestLbConfig_{
|
||||
LeastRequestLbConfig: &envoy.Cluster_LeastRequestLbConfig{
|
||||
ChoiceCount: &wrappers.UInt32Value{Value: l.LeastRequestConfig.ChoiceCount},
|
||||
},
|
||||
}
|
||||
case "round_robin":
|
||||
c.LbPolicy = envoy.Cluster_ROUND_ROBIN
|
||||
case "random":
|
||||
c.LbPolicy = envoy.Cluster_RANDOM
|
||||
case "ring_hash":
|
||||
c.LbPolicy = envoy.Cluster_RING_HASH
|
||||
c.LbConfig = &envoy.Cluster_RingHashLbConfig_{
|
||||
RingHashLbConfig: &envoy.Cluster_RingHashLbConfig{
|
||||
MinimumRingSize: &wrappers.UInt64Value{Value: l.RingHashConfig.MinimumRingSize},
|
||||
MaximumRingSize: &wrappers.UInt64Value{Value: l.RingHashConfig.MaximumRingSize},
|
||||
},
|
||||
}
|
||||
case "maglev":
|
||||
c.LbPolicy = envoy.Cluster_MAGLEV
|
||||
default:
|
||||
return fmt.Errorf("unsupported load balancer policy %q for cluster %q", l.Policy, c.Name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// makeClusterFromUserConfig returns the listener config decoded from an
|
||||
// arbitrary proto3 json format string or an error if it's invalid.
|
||||
//
|
||||
|
|
|
@ -2,7 +2,6 @@ package xds
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/golang/protobuf/ptypes/wrappers"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"testing"
|
||||
|
@ -367,10 +366,12 @@ func TestClustersFromSnapshot(t *testing.T) {
|
|||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
LoadBalancer: structs.LoadBalancer{
|
||||
Policy: "least_request",
|
||||
LeastRequestConfig: structs.LeastRequestConfig{
|
||||
ChoiceCount: 5,
|
||||
LoadBalancer: &structs.LoadBalancer{
|
||||
EnvoyLBConfig: &structs.EnvoyLBConfig{
|
||||
Policy: "least_request",
|
||||
LeastRequestConfig: &structs.LeastRequestConfig{
|
||||
ChoiceCount: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -394,11 +395,13 @@ func TestClustersFromSnapshot(t *testing.T) {
|
|||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
LoadBalancer: structs.LoadBalancer{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: structs.RingHashConfig{
|
||||
MinimumRingSize: 20,
|
||||
MaximumRingSize: 50,
|
||||
LoadBalancer: &structs.LoadBalancer{
|
||||
EnvoyLBConfig: &structs.EnvoyLBConfig{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: &structs.RingHashConfig{
|
||||
MinimumRingSize: 20,
|
||||
MaximumRingSize: 50,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -605,11 +608,13 @@ func TestClustersFromSnapshot(t *testing.T) {
|
|||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
LoadBalancer: structs.LoadBalancer{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: structs.RingHashConfig{
|
||||
MinimumRingSize: 20,
|
||||
MaximumRingSize: 50,
|
||||
LoadBalancer: &structs.LoadBalancer{
|
||||
EnvoyLBConfig: &structs.EnvoyLBConfig{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: &structs.RingHashConfig{
|
||||
MinimumRingSize: 20,
|
||||
MaximumRingSize: 50,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -834,86 +839,3 @@ func setupTLSRootsAndLeaf(t *testing.T, snap *proxycfg.ConfigSnapshot) {
|
|||
snap.Roots.Roots[0].RootCert = golden(t, "test-root-cert", "", "")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadBalancer_injectLBToCluster(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
lb structs.LoadBalancer
|
||||
expected envoy.Cluster
|
||||
}{
|
||||
{
|
||||
name: "skip empty",
|
||||
lb: structs.LoadBalancer{
|
||||
Policy: "",
|
||||
},
|
||||
expected: envoy.Cluster{},
|
||||
},
|
||||
{
|
||||
name: "round_robin",
|
||||
lb: structs.LoadBalancer{
|
||||
Policy: "round_robin",
|
||||
},
|
||||
expected: envoy.Cluster{LbPolicy: envoy.Cluster_ROUND_ROBIN},
|
||||
},
|
||||
{
|
||||
name: "random",
|
||||
lb: structs.LoadBalancer{
|
||||
Policy: "random",
|
||||
},
|
||||
expected: envoy.Cluster{LbPolicy: envoy.Cluster_RANDOM},
|
||||
},
|
||||
{
|
||||
name: "maglev",
|
||||
lb: structs.LoadBalancer{
|
||||
Policy: "maglev",
|
||||
},
|
||||
expected: envoy.Cluster{LbPolicy: envoy.Cluster_MAGLEV},
|
||||
},
|
||||
{
|
||||
name: "ring_hash",
|
||||
lb: structs.LoadBalancer{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: structs.RingHashConfig{
|
||||
MinimumRingSize: 3,
|
||||
MaximumRingSize: 7,
|
||||
},
|
||||
},
|
||||
expected: envoy.Cluster{
|
||||
LbPolicy: envoy.Cluster_RING_HASH,
|
||||
LbConfig: &envoy.Cluster_RingHashLbConfig_{
|
||||
RingHashLbConfig: &envoy.Cluster_RingHashLbConfig{
|
||||
MinimumRingSize: &wrappers.UInt64Value{Value: 3},
|
||||
MaximumRingSize: &wrappers.UInt64Value{Value: 7},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "least_request",
|
||||
lb: structs.LoadBalancer{
|
||||
Policy: "least_request",
|
||||
LeastRequestConfig: structs.LeastRequestConfig{
|
||||
ChoiceCount: 3,
|
||||
},
|
||||
},
|
||||
expected: envoy.Cluster{
|
||||
LbPolicy: envoy.Cluster_LEAST_REQUEST,
|
||||
LbConfig: &envoy.Cluster_LeastRequestLbConfig_{
|
||||
LeastRequestLbConfig: &envoy.Cluster_LeastRequestLbConfig{
|
||||
ChoiceCount: &wrappers.UInt32Value{Value: 3},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var c envoy.Cluster
|
||||
err := injectLBToCluster(tc.lb, &c)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, tc.expected, c)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,14 +43,14 @@ func routesFromSnapshotTerminatingGateway(_ connectionInfo, cfgSnap *proxycfg.Co
|
|||
}
|
||||
|
||||
var resources []proto.Message
|
||||
for svc := range cfgSnap.TerminatingGateway.ServiceGroups {
|
||||
for _, svc := range cfgSnap.TerminatingGateway.ValidServices() {
|
||||
clusterName := connect.ServiceSNI(svc.Name, "", svc.NamespaceOrDefault(), cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain)
|
||||
resolver, hasResolver := cfgSnap.TerminatingGateway.ServiceResolvers[svc]
|
||||
|
||||
svcConfig := cfgSnap.TerminatingGateway.ServiceConfigs[svc]
|
||||
|
||||
cfg, err := ParseProxyConfig(svcConfig.ProxyConfig)
|
||||
if err != nil || cfg.Protocol != "http" {
|
||||
if err != nil || structs.IsProtocolHTTPLike(cfg.Protocol) {
|
||||
// Routes can only be defined for HTTP services
|
||||
continue
|
||||
}
|
||||
|
@ -59,7 +59,12 @@ func routesFromSnapshotTerminatingGateway(_ connectionInfo, cfgSnap *proxycfg.Co
|
|||
// Use a zero value resolver with no timeout and no subsets
|
||||
resolver = &structs.ServiceResolverConfigEntry{}
|
||||
}
|
||||
route, err := makeNamedDefaultRouteWithLB(clusterName, resolver.LoadBalancer)
|
||||
|
||||
var lb *structs.EnvoyLBConfig
|
||||
if resolver.LoadBalancer != nil {
|
||||
lb = resolver.LoadBalancer.EnvoyLBConfig
|
||||
}
|
||||
route, err := makeNamedDefaultRouteWithLB(clusterName, lb)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
@ -68,7 +73,7 @@ func routesFromSnapshotTerminatingGateway(_ connectionInfo, cfgSnap *proxycfg.Co
|
|||
// If there is a service-resolver for this service then also setup routes for each subset
|
||||
for name := range resolver.Subsets {
|
||||
clusterName = connect.ServiceSNI(svc.Name, name, svc.NamespaceOrDefault(), cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain)
|
||||
route, err := makeNamedDefaultRouteWithLB(clusterName, resolver.LoadBalancer)
|
||||
route, err := makeNamedDefaultRouteWithLB(clusterName, lb)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
@ -76,13 +81,13 @@ func routesFromSnapshotTerminatingGateway(_ connectionInfo, cfgSnap *proxycfg.Co
|
|||
}
|
||||
}
|
||||
|
||||
// TODO(rb): make sure we don't generate an empty result
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
func makeNamedDefaultRouteWithLB(clusterName string, lb structs.LoadBalancer) (*envoy.RouteConfiguration, error) {
|
||||
func makeNamedDefaultRouteWithLB(clusterName string, lb *structs.EnvoyLBConfig) (*envoy.RouteConfiguration, error) {
|
||||
action := makeRouteActionFromName(clusterName)
|
||||
if err := injectLBToRouteAction(lb, action.Route); err != nil {
|
||||
|
||||
if err := lb.InjectToRouteAction(action.Route); err != nil {
|
||||
return nil, fmt.Errorf("failed to apply load balancer configuration to route action: %v", err)
|
||||
}
|
||||
|
||||
|
@ -250,6 +255,8 @@ func makeUpstreamRouteForDiscoveryChain(
|
|||
return nil, fmt.Errorf("missing first node in compiled discovery chain for: %s", chain.ServiceName)
|
||||
}
|
||||
|
||||
var lb *structs.EnvoyLBConfig
|
||||
|
||||
switch startNode.Type {
|
||||
case structs.DiscoveryGraphNodeTypeRouter:
|
||||
routes = make([]*envoyroute.Route, 0, len(startNode.Routes))
|
||||
|
@ -263,6 +270,10 @@ func makeUpstreamRouteForDiscoveryChain(
|
|||
)
|
||||
|
||||
nextNode := chain.Nodes[discoveryRoute.NextNode]
|
||||
if nextNode.LoadBalancer != nil {
|
||||
lb = nextNode.LoadBalancer.EnvoyLBConfig
|
||||
}
|
||||
|
||||
switch nextNode.Type {
|
||||
case structs.DiscoveryGraphNodeTypeSplitter:
|
||||
routeAction, err = makeRouteActionForSplitter(nextNode.Splits, chain)
|
||||
|
@ -270,14 +281,14 @@ func makeUpstreamRouteForDiscoveryChain(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if err := injectLBToRouteAction(nextNode.LoadBalancer, routeAction.Route); err != nil {
|
||||
if err := lb.InjectToRouteAction(routeAction.Route); err != nil {
|
||||
return nil, fmt.Errorf("failed to apply load balancer configuration to route action: %v", err)
|
||||
}
|
||||
|
||||
case structs.DiscoveryGraphNodeTypeResolver:
|
||||
routeAction = makeRouteActionForChainCluster(nextNode.Resolver.Target, chain)
|
||||
|
||||
if err := injectLBToRouteAction(nextNode.LoadBalancer, routeAction.Route); err != nil {
|
||||
if err := lb.InjectToRouteAction(routeAction.Route); err != nil {
|
||||
return nil, fmt.Errorf("failed to apply load balancer configuration to route action: %v", err)
|
||||
}
|
||||
|
||||
|
@ -332,7 +343,10 @@ func makeUpstreamRouteForDiscoveryChain(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if err := injectLBToRouteAction(startNode.LoadBalancer, routeAction.Route); err != nil {
|
||||
if startNode.LoadBalancer != nil {
|
||||
lb = startNode.LoadBalancer.EnvoyLBConfig
|
||||
}
|
||||
if err := lb.InjectToRouteAction(routeAction.Route); err != nil {
|
||||
return nil, fmt.Errorf("failed to apply load balancer configuration to route action: %v", err)
|
||||
}
|
||||
|
||||
|
@ -346,7 +360,10 @@ func makeUpstreamRouteForDiscoveryChain(
|
|||
case structs.DiscoveryGraphNodeTypeResolver:
|
||||
routeAction := makeRouteActionForChainCluster(startNode.Resolver.Target, chain)
|
||||
|
||||
if err := injectLBToRouteAction(startNode.LoadBalancer, routeAction.Route); err != nil {
|
||||
if startNode.LoadBalancer != nil {
|
||||
lb = startNode.LoadBalancer.EnvoyLBConfig
|
||||
}
|
||||
if err := lb.InjectToRouteAction(routeAction.Route); err != nil {
|
||||
return nil, fmt.Errorf("failed to apply load balancer configuration to route action: %v", err)
|
||||
}
|
||||
|
||||
|
@ -370,62 +387,6 @@ func makeUpstreamRouteForDiscoveryChain(
|
|||
return host, nil
|
||||
}
|
||||
|
||||
func injectLBToRouteAction(lb structs.LoadBalancer, action *envoyroute.RouteAction) error {
|
||||
if !lb.IsHashBased() {
|
||||
return nil
|
||||
}
|
||||
|
||||
result := make([]*envoyroute.RouteAction_HashPolicy, 0, len(lb.HashPolicies))
|
||||
for _, policy := range lb.HashPolicies {
|
||||
if policy.SourceAddress {
|
||||
result = append(result, &envoyroute.RouteAction_HashPolicy{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_ConnectionProperties_{
|
||||
ConnectionProperties: &envoyroute.RouteAction_HashPolicy_ConnectionProperties{
|
||||
SourceIp: true,
|
||||
},
|
||||
},
|
||||
Terminal: policy.Terminal,
|
||||
})
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
switch policy.Field {
|
||||
case "header":
|
||||
result = append(result, &envoyroute.RouteAction_HashPolicy{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_Header_{
|
||||
Header: &envoyroute.RouteAction_HashPolicy_Header{
|
||||
HeaderName: policy.FieldMatchValue,
|
||||
},
|
||||
},
|
||||
Terminal: policy.Terminal,
|
||||
})
|
||||
case "cookie":
|
||||
result = append(result, &envoyroute.RouteAction_HashPolicy{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_Cookie_{
|
||||
Cookie: &envoyroute.RouteAction_HashPolicy_Cookie{
|
||||
Name: policy.FieldMatchValue,
|
||||
},
|
||||
},
|
||||
Terminal: policy.Terminal,
|
||||
})
|
||||
case "query_parameter":
|
||||
result = append(result, &envoyroute.RouteAction_HashPolicy{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_QueryParameter_{
|
||||
QueryParameter: &envoyroute.RouteAction_HashPolicy_QueryParameter{
|
||||
Name: policy.FieldMatchValue,
|
||||
},
|
||||
},
|
||||
Terminal: policy.Terminal,
|
||||
})
|
||||
default:
|
||||
return fmt.Errorf("unsupported load balancer hash policy field: %v", policy.Field)
|
||||
}
|
||||
}
|
||||
action.HashPolicy = result
|
||||
return nil
|
||||
}
|
||||
|
||||
func makeRouteMatchForDiscoveryRoute(_ connectionInfo, discoveryRoute *structs.DiscoveryRoute) *envoyroute.RouteMatch {
|
||||
match := discoveryRoute.Definition.Match
|
||||
if match == nil || match.IsEmpty() {
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"time"
|
||||
|
||||
envoy "github.com/envoyproxy/go-control-plane/envoy/api/v2"
|
||||
envoyroute "github.com/envoyproxy/go-control-plane/envoy/api/v2/route"
|
||||
"github.com/hashicorp/consul/agent/connect"
|
||||
"github.com/hashicorp/consul/agent/consul/discoverychain"
|
||||
"github.com/hashicorp/consul/agent/proxycfg"
|
||||
|
@ -203,25 +202,27 @@ func TestRoutesFromSnapshot(t *testing.T) {
|
|||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
LoadBalancer: structs.LoadBalancer{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: structs.RingHashConfig{
|
||||
MinimumRingSize: 20,
|
||||
MaximumRingSize: 50,
|
||||
},
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
Field: "cookie",
|
||||
FieldMatchValue: "chocolate-chip",
|
||||
Terminal: true,
|
||||
LoadBalancer: &structs.LoadBalancer{
|
||||
EnvoyLBConfig: &structs.EnvoyLBConfig{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: &structs.RingHashConfig{
|
||||
MinimumRingSize: 20,
|
||||
MaximumRingSize: 50,
|
||||
},
|
||||
{
|
||||
Field: "header",
|
||||
FieldMatchValue: "x-user-id",
|
||||
},
|
||||
{
|
||||
SourceAddress: true,
|
||||
Terminal: true,
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
Field: structs.HashPolicyCookie,
|
||||
FieldValue: "chocolate-chip",
|
||||
Terminal: true,
|
||||
},
|
||||
{
|
||||
Field: structs.HashPolicyHeader,
|
||||
FieldValue: "x-user-id",
|
||||
},
|
||||
{
|
||||
SourceIP: true,
|
||||
Terminal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -276,178 +277,3 @@ func TestRoutesFromSnapshot(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadBalancer_injectLBToRouteAction(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
lb structs.LoadBalancer
|
||||
expected envoyroute.RouteAction
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
lb: structs.LoadBalancer{
|
||||
Policy: "",
|
||||
},
|
||||
// we only modify route actions for hash-based LB policies
|
||||
expected: envoyroute.RouteAction{},
|
||||
},
|
||||
{
|
||||
name: "least_request",
|
||||
lb: structs.LoadBalancer{
|
||||
Policy: "least_request",
|
||||
LeastRequestConfig: structs.LeastRequestConfig{
|
||||
ChoiceCount: 3,
|
||||
},
|
||||
},
|
||||
// we only modify route actions for hash-based LB policies
|
||||
expected: envoyroute.RouteAction{},
|
||||
},
|
||||
{
|
||||
name: "header",
|
||||
lb: structs.LoadBalancer{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: structs.RingHashConfig{
|
||||
MinimumRingSize: 3,
|
||||
MaximumRingSize: 7,
|
||||
},
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
Field: "header",
|
||||
FieldMatchValue: "x-route-key",
|
||||
Terminal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: envoyroute.RouteAction{
|
||||
HashPolicy: []*envoyroute.RouteAction_HashPolicy{
|
||||
{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_Header_{
|
||||
Header: &envoyroute.RouteAction_HashPolicy_Header{
|
||||
HeaderName: "x-route-key",
|
||||
},
|
||||
},
|
||||
Terminal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "cookies",
|
||||
lb: structs.LoadBalancer{
|
||||
Policy: "maglev",
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
Field: "cookie",
|
||||
FieldMatchValue: "red-velvet",
|
||||
Terminal: true,
|
||||
},
|
||||
{
|
||||
Field: "cookie",
|
||||
FieldMatchValue: "oatmeal",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: envoyroute.RouteAction{
|
||||
HashPolicy: []*envoyroute.RouteAction_HashPolicy{
|
||||
{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_Cookie_{
|
||||
Cookie: &envoyroute.RouteAction_HashPolicy_Cookie{
|
||||
Name: "red-velvet",
|
||||
},
|
||||
},
|
||||
Terminal: true,
|
||||
},
|
||||
{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_Cookie_{
|
||||
Cookie: &envoyroute.RouteAction_HashPolicy_Cookie{
|
||||
Name: "oatmeal",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "source addr",
|
||||
lb: structs.LoadBalancer{
|
||||
Policy: "maglev",
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
SourceAddress: true,
|
||||
Terminal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: envoyroute.RouteAction{
|
||||
HashPolicy: []*envoyroute.RouteAction_HashPolicy{
|
||||
{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_ConnectionProperties_{
|
||||
ConnectionProperties: &envoyroute.RouteAction_HashPolicy_ConnectionProperties{
|
||||
SourceIp: true,
|
||||
},
|
||||
},
|
||||
Terminal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "kitchen sink",
|
||||
lb: structs.LoadBalancer{
|
||||
Policy: "maglev",
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
SourceAddress: true,
|
||||
Terminal: true,
|
||||
},
|
||||
{
|
||||
Field: "cookie",
|
||||
FieldMatchValue: "oatmeal",
|
||||
},
|
||||
{
|
||||
Field: "header",
|
||||
FieldMatchValue: "special-header",
|
||||
Terminal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: envoyroute.RouteAction{
|
||||
HashPolicy: []*envoyroute.RouteAction_HashPolicy{
|
||||
{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_ConnectionProperties_{
|
||||
ConnectionProperties: &envoyroute.RouteAction_HashPolicy_ConnectionProperties{
|
||||
SourceIp: true,
|
||||
},
|
||||
},
|
||||
Terminal: true,
|
||||
},
|
||||
{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_Cookie_{
|
||||
Cookie: &envoyroute.RouteAction_HashPolicy_Cookie{
|
||||
Name: "oatmeal",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
PolicySpecifier: &envoyroute.RouteAction_HashPolicy_Header_{
|
||||
Header: &envoyroute.RouteAction_HashPolicy_Header{
|
||||
HeaderName: "special-header",
|
||||
},
|
||||
},
|
||||
Terminal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
ra := &envoyroute.RouteAction{}
|
||||
err := injectLBToRouteAction(tc.lb, ra)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, &tc.expected, ra)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,38 +111,6 @@
|
|||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -111,38 +111,6 @@
|
|||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -111,38 +111,6 @@
|
|||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -111,38 +111,6 @@
|
|||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -111,38 +111,6 @@
|
|||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -111,38 +111,6 @@
|
|||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -111,38 +111,6 @@
|
|||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -111,38 +111,6 @@
|
|||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "10s",
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
|
@ -111,38 +111,6 @@
|
|||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "10s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "10s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "10s",
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
|
@ -111,38 +111,6 @@
|
|||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "10s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "10s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "10s",
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
|
@ -111,38 +111,6 @@
|
|||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "10s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "10s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "10s",
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
|
@ -111,38 +111,6 @@
|
|||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "10s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "10s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -1,60 +1,6 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "alt.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "LOGICAL_DNS",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "alt.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "api.altdomain",
|
||||
"portValue": 8081
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"filename": "api.cert.pem"
|
||||
},
|
||||
"privateKey": {
|
||||
"filename": "api.key.pem"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"filename": "ca.cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"dnsRefreshRate": "10s",
|
||||
"dnsLookupFamily": "V4_ONLY",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
|
@ -173,38 +119,6 @@
|
|||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "LOGICAL_DNS",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "cache.mydomain",
|
||||
"portValue": 8081
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "UNHEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"dnsRefreshRate": "10s",
|
||||
"dnsLookupFamily": "V4_ONLY",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
|
|
|
@ -1,60 +1,6 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "alt.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "LOGICAL_DNS",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "alt.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "api.altdomain",
|
||||
"portValue": 8081
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"filename": "api.cert.pem"
|
||||
},
|
||||
"privateKey": {
|
||||
"filename": "api.key.pem"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"filename": "ca.cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"dnsRefreshRate": "10s",
|
||||
"dnsLookupFamily": "V4_ONLY",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
|
@ -173,38 +119,6 @@
|
|||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "LOGICAL_DNS",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "cache.mydomain",
|
||||
"portValue": 8081
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "UNHEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"dnsRefreshRate": "10s",
|
||||
"dnsLookupFamily": "V4_ONLY",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
|
|
|
@ -1,60 +1,6 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "alt.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "LOGICAL_DNS",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "alt.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "api.altdomain",
|
||||
"portValue": 8081
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"filename": "api.cert.pem"
|
||||
},
|
||||
"privateKey": {
|
||||
"filename": "api.key.pem"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"filename": "ca.cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"dnsRefreshRate": "10s",
|
||||
"dnsLookupFamily": "V4_ONLY",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
|
@ -173,38 +119,6 @@
|
|||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "LOGICAL_DNS",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "cache.mydomain",
|
||||
"portValue": 8081
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "UNHEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"dnsRefreshRate": "10s",
|
||||
"dnsLookupFamily": "V4_ONLY",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
|
|
|
@ -1,60 +1,6 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "alt.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "LOGICAL_DNS",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "alt.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "api.altdomain",
|
||||
"portValue": 8081
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"filename": "api.cert.pem"
|
||||
},
|
||||
"privateKey": {
|
||||
"filename": "api.key.pem"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"filename": "ca.cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"dnsRefreshRate": "10s",
|
||||
"dnsLookupFamily": "V4_ONLY",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
|
@ -173,38 +119,6 @@
|
|||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "LOGICAL_DNS",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "cache.mydomain",
|
||||
"portValue": 8081
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "UNHEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"dnsRefreshRate": "10s",
|
||||
"dnsLookupFamily": "V4_ONLY",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
|
|
|
@ -119,62 +119,6 @@
|
|||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"filename": "ca.cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"filename": "ca.cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
|
|
|
@ -119,62 +119,6 @@
|
|||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"filename": "ca.cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"filename": "ca.cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
|
|
|
@ -119,62 +119,6 @@
|
|||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"filename": "ca.cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"filename": "ca.cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
|
|
|
@ -119,62 +119,6 @@
|
|||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"filename": "ca.cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"filename": "ca.cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
|
|
|
@ -119,94 +119,6 @@
|
|||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "LOGICAL_DNS",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "cache.mydomain",
|
||||
"portValue": 8081
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "UNHEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"dnsRefreshRate": "10s",
|
||||
"dnsLookupFamily": "V4_ONLY",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"filename": "ca.cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"filename": "ca.cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
|
|
|
@ -119,94 +119,6 @@
|
|||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "LOGICAL_DNS",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "cache.mydomain",
|
||||
"portValue": 8081
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "UNHEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"dnsRefreshRate": "10s",
|
||||
"dnsLookupFamily": "V4_ONLY",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"filename": "ca.cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"filename": "ca.cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
|
|
|
@ -119,94 +119,6 @@
|
|||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "LOGICAL_DNS",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "cache.mydomain",
|
||||
"portValue": 8081
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "UNHEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"dnsRefreshRate": "10s",
|
||||
"dnsLookupFamily": "V4_ONLY",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"filename": "ca.cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"filename": "ca.cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
|
|
|
@ -119,94 +119,6 @@
|
|||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "LOGICAL_DNS",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "cache.mydomain",
|
||||
"portValue": 8081
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "UNHEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"dnsRefreshRate": "10s",
|
||||
"dnsLookupFamily": "V4_ONLY",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"filename": "ca.cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"filename": "ca.cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"domains": [
|
||||
"*"
|
||||
],
|
||||
|
@ -16,26 +16,7 @@
|
|||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"hashPolicy": [
|
||||
{
|
||||
"cookie": {
|
||||
"name": "chocolate-chip"
|
||||
},
|
||||
"terminal": true
|
||||
},
|
||||
{
|
||||
"header": {
|
||||
"headerName": "x-user-id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"connectionProperties": {
|
||||
"sourceIp": true
|
||||
},
|
||||
"terminal": true
|
||||
}
|
||||
]
|
||||
"cluster": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -45,10 +26,10 @@
|
|||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"domains": [
|
||||
"*"
|
||||
],
|
||||
|
@ -58,26 +39,7 @@
|
|||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"hashPolicy": [
|
||||
{
|
||||
"cookie": {
|
||||
"name": "chocolate-chip"
|
||||
},
|
||||
"terminal": true
|
||||
},
|
||||
{
|
||||
"header": {
|
||||
"headerName": "x-user-id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"connectionProperties": {
|
||||
"sourceIp": true
|
||||
},
|
||||
"terminal": true
|
||||
}
|
||||
]
|
||||
"cluster": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -87,10 +49,10 @@
|
|||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"domains": [
|
||||
"*"
|
||||
],
|
||||
|
@ -100,26 +62,7 @@
|
|||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"hashPolicy": [
|
||||
{
|
||||
"cookie": {
|
||||
"name": "chocolate-chip"
|
||||
},
|
||||
"terminal": true
|
||||
},
|
||||
{
|
||||
"header": {
|
||||
"headerName": "x-user-id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"connectionProperties": {
|
||||
"sourceIp": true
|
||||
},
|
||||
"terminal": true
|
||||
}
|
||||
]
|
||||
"cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"domains": [
|
||||
"*"
|
||||
],
|
||||
|
@ -16,26 +16,7 @@
|
|||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"hashPolicy": [
|
||||
{
|
||||
"cookie": {
|
||||
"name": "chocolate-chip"
|
||||
},
|
||||
"terminal": true
|
||||
},
|
||||
{
|
||||
"header": {
|
||||
"headerName": "x-user-id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"connectionProperties": {
|
||||
"sourceIp": true
|
||||
},
|
||||
"terminal": true
|
||||
}
|
||||
]
|
||||
"cluster": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -45,10 +26,10 @@
|
|||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"domains": [
|
||||
"*"
|
||||
],
|
||||
|
@ -58,26 +39,7 @@
|
|||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"hashPolicy": [
|
||||
{
|
||||
"cookie": {
|
||||
"name": "chocolate-chip"
|
||||
},
|
||||
"terminal": true
|
||||
},
|
||||
{
|
||||
"header": {
|
||||
"headerName": "x-user-id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"connectionProperties": {
|
||||
"sourceIp": true
|
||||
},
|
||||
"terminal": true
|
||||
}
|
||||
]
|
||||
"cluster": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -87,10 +49,10 @@
|
|||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"domains": [
|
||||
"*"
|
||||
],
|
||||
|
@ -100,26 +62,7 @@
|
|||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"hashPolicy": [
|
||||
{
|
||||
"cookie": {
|
||||
"name": "chocolate-chip"
|
||||
},
|
||||
"terminal": true
|
||||
},
|
||||
{
|
||||
"header": {
|
||||
"headerName": "x-user-id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"connectionProperties": {
|
||||
"sourceIp": true
|
||||
},
|
||||
"terminal": true
|
||||
}
|
||||
]
|
||||
"cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"domains": [
|
||||
"*"
|
||||
],
|
||||
|
@ -16,26 +16,7 @@
|
|||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"hashPolicy": [
|
||||
{
|
||||
"cookie": {
|
||||
"name": "chocolate-chip"
|
||||
},
|
||||
"terminal": true
|
||||
},
|
||||
{
|
||||
"header": {
|
||||
"headerName": "x-user-id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"connectionProperties": {
|
||||
"sourceIp": true
|
||||
},
|
||||
"terminal": true
|
||||
}
|
||||
]
|
||||
"cluster": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -45,10 +26,10 @@
|
|||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"domains": [
|
||||
"*"
|
||||
],
|
||||
|
@ -58,26 +39,7 @@
|
|||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"hashPolicy": [
|
||||
{
|
||||
"cookie": {
|
||||
"name": "chocolate-chip"
|
||||
},
|
||||
"terminal": true
|
||||
},
|
||||
{
|
||||
"header": {
|
||||
"headerName": "x-user-id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"connectionProperties": {
|
||||
"sourceIp": true
|
||||
},
|
||||
"terminal": true
|
||||
}
|
||||
]
|
||||
"cluster": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -87,10 +49,10 @@
|
|||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"domains": [
|
||||
"*"
|
||||
],
|
||||
|
@ -100,26 +62,7 @@
|
|||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"hashPolicy": [
|
||||
{
|
||||
"cookie": {
|
||||
"name": "chocolate-chip"
|
||||
},
|
||||
"terminal": true
|
||||
},
|
||||
{
|
||||
"header": {
|
||||
"headerName": "x-user-id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"connectionProperties": {
|
||||
"sourceIp": true
|
||||
},
|
||||
"terminal": true
|
||||
}
|
||||
]
|
||||
"cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"domains": [
|
||||
"*"
|
||||
],
|
||||
|
@ -16,26 +16,7 @@
|
|||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"hashPolicy": [
|
||||
{
|
||||
"cookie": {
|
||||
"name": "chocolate-chip"
|
||||
},
|
||||
"terminal": true
|
||||
},
|
||||
{
|
||||
"header": {
|
||||
"headerName": "x-user-id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"connectionProperties": {
|
||||
"sourceIp": true
|
||||
},
|
||||
"terminal": true
|
||||
}
|
||||
]
|
||||
"cluster": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -45,10 +26,10 @@
|
|||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"domains": [
|
||||
"*"
|
||||
],
|
||||
|
@ -58,26 +39,7 @@
|
|||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"hashPolicy": [
|
||||
{
|
||||
"cookie": {
|
||||
"name": "chocolate-chip"
|
||||
},
|
||||
"terminal": true
|
||||
},
|
||||
{
|
||||
"header": {
|
||||
"headerName": "x-user-id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"connectionProperties": {
|
||||
"sourceIp": true
|
||||
},
|
||||
"terminal": true
|
||||
}
|
||||
]
|
||||
"cluster": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -87,10 +49,10 @@
|
|||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"domains": [
|
||||
"*"
|
||||
],
|
||||
|
@ -100,26 +62,7 @@
|
|||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"hashPolicy": [
|
||||
{
|
||||
"cookie": {
|
||||
"name": "chocolate-chip"
|
||||
},
|
||||
"terminal": true
|
||||
},
|
||||
{
|
||||
"header": {
|
||||
"headerName": "x-user-id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"connectionProperties": {
|
||||
"sourceIp": true
|
||||
},
|
||||
"terminal": true
|
||||
}
|
||||
]
|
||||
"cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -140,7 +140,7 @@ type ServiceResolverConfigEntry struct {
|
|||
|
||||
// LoadBalancer determines the load balancing policy and configuration for services
|
||||
// issuing requests to this upstream service.
|
||||
LoadBalancer LoadBalancer `json:",omitempty" alias:"load_balancer"`
|
||||
LoadBalancer *LoadBalancer `json:",omitempty" alias:"load_balancer"`
|
||||
|
||||
CreateIndex uint64
|
||||
ModifyIndex uint64
|
||||
|
@ -209,14 +209,22 @@ type ServiceResolverFailover struct {
|
|||
// LoadBalancer determines the load balancing policy and configuration for services
|
||||
// issuing requests to this upstream service.
|
||||
type LoadBalancer struct {
|
||||
// EnvoyLBConfig contains Envoy-specific load balancing configuration for this upstream
|
||||
EnvoyLBConfig *EnvoyLBConfig `json:",omitempty" alias:"envoy_lb_config"`
|
||||
|
||||
// OpaqueConfig contains load balancing configuration opaque to Consul for 3rd party proxies
|
||||
OpaqueConfig string `json:",omitempty" alias:"opaque_config"`
|
||||
}
|
||||
|
||||
type EnvoyLBConfig struct {
|
||||
// Policy is the load balancing policy used to select a host
|
||||
Policy string `json:",omitempty"`
|
||||
|
||||
// RingHashConfig contains configuration for the "ring_hash" policy type
|
||||
RingHashConfig RingHashConfig `json:",omitempty" alias:"ring_hash_config"`
|
||||
RingHashConfig *RingHashConfig `json:",omitempty" alias:"ring_hash_config"`
|
||||
|
||||
// LeastRequestConfig contains configuration for the "least_request" policy type
|
||||
LeastRequestConfig LeastRequestConfig `json:",omitempty" alias:"least_request_config"`
|
||||
LeastRequestConfig *LeastRequestConfig `json:",omitempty" alias:"least_request_config"`
|
||||
|
||||
// HashPolicies is a list of hash policies to use for hashing load balancing algorithms.
|
||||
// Hash policies are evaluated individually and combined such that identical lists
|
||||
|
@ -241,28 +249,37 @@ type LeastRequestConfig struct {
|
|||
ChoiceCount uint32 `json:",omitempty" alias:"choice_count"`
|
||||
}
|
||||
|
||||
// HashPolicy is a list of hash policies to use for hashing load balancing algorithms.
|
||||
// Hash policies are evaluated individually and combined such that identical lists
|
||||
// result in the same hash.
|
||||
// If no hash policies are present, or none are successfully evaluated,
|
||||
// then a random backend host will be selected.
|
||||
// HashPolicy defines which attributes will be hashed by hash-based LB algorithms
|
||||
type HashPolicy struct {
|
||||
// Field is the attribute type to hash on.
|
||||
// Must be one of "header","cookie", or "query_parameter".
|
||||
// Cannot be specified along with SourceIP.
|
||||
Field string `json:",omitempty"`
|
||||
|
||||
// FieldMatchValue is the value to hash.
|
||||
// FieldValue is the value to hash.
|
||||
// ie. header name, cookie name, URL query parameter name
|
||||
// Cannot be specified along with SourceIP.
|
||||
FieldMatchValue string `json:",omitempty" alias:"field_value"`
|
||||
FieldValue string `json:",omitempty" alias:"field_value"`
|
||||
|
||||
// SourceAddress determines whether the hash should be of the source IP rather than of a field and field value.
|
||||
// Cannot be specified along with Field and FieldMatchValue.
|
||||
SourceAddress bool `json:",omitempty" alias:"source_address"`
|
||||
// CookieConfig contains configuration for the "cookie" hash policy type.
|
||||
CookieConfig *CookieConfig `json:",omitempty" alias:"cookie_config"`
|
||||
|
||||
// SourceIP determines whether the hash should be of the source IP rather than of a field and field value.
|
||||
// Cannot be specified along with Field or FieldValue.
|
||||
SourceIP bool `json:",omitempty" alias:"source_ip"`
|
||||
|
||||
// Terminal will short circuit the computation of the hash when multiple hash policies are present.
|
||||
// If a hash is computed when a Terminal policy is evaluated,
|
||||
// then that hash will be used and subsequent hash policies will be ignored.
|
||||
Terminal bool `json:",omitempty"`
|
||||
}
|
||||
|
||||
// CookieConfig contains configuration for the "cookie" hash policy type.
|
||||
// This is specified to have Envoy generate a cookie for a client on its first request.
|
||||
type CookieConfig struct {
|
||||
// TTL for generated cookies
|
||||
TTL time.Duration `json:",omitempty"`
|
||||
|
||||
// The path to set for the cookie
|
||||
Path string `json:",omitempty"`
|
||||
}
|
||||
|
|
|
@ -293,9 +293,11 @@ func TestAPI_ConfigEntry_ServiceResolver_LoadBalancer(t *testing.T) {
|
|||
Kind: ServiceResolver,
|
||||
Name: "test-least-req",
|
||||
Namespace: defaultNamespace,
|
||||
LoadBalancer: LoadBalancer{
|
||||
Policy: "least_request",
|
||||
LeastRequestConfig: LeastRequestConfig{ChoiceCount: 10},
|
||||
LoadBalancer: &LoadBalancer{
|
||||
EnvoyLBConfig: &EnvoyLBConfig{
|
||||
Policy: "least_request",
|
||||
LeastRequestConfig: &LeastRequestConfig{ChoiceCount: 10},
|
||||
},
|
||||
},
|
||||
},
|
||||
verify: verifyResolver,
|
||||
|
@ -306,20 +308,30 @@ func TestAPI_ConfigEntry_ServiceResolver_LoadBalancer(t *testing.T) {
|
|||
Kind: ServiceResolver,
|
||||
Name: "test-ring-hash",
|
||||
Namespace: defaultNamespace,
|
||||
LoadBalancer: LoadBalancer{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: RingHashConfig{
|
||||
MinimumRingSize: 1024 * 2,
|
||||
MaximumRingSize: 1024 * 4,
|
||||
},
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
Field: "header",
|
||||
FieldMatchValue: "my-session-header",
|
||||
Terminal: true,
|
||||
LoadBalancer: &LoadBalancer{
|
||||
EnvoyLBConfig: &EnvoyLBConfig{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: &RingHashConfig{
|
||||
MinimumRingSize: 1024 * 2,
|
||||
MaximumRingSize: 1024 * 4,
|
||||
},
|
||||
{
|
||||
SourceAddress: true,
|
||||
HashPolicies: []HashPolicy{
|
||||
{
|
||||
Field: "header",
|
||||
FieldValue: "my-session-header",
|
||||
Terminal: true,
|
||||
},
|
||||
{
|
||||
Field: "cookie",
|
||||
FieldValue: "oreo",
|
||||
CookieConfig: &CookieConfig{
|
||||
Path: "/tray",
|
||||
TTL: 20 * time.Millisecond,
|
||||
},
|
||||
},
|
||||
{
|
||||
SourceIP: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package write
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
|
@ -1165,6 +1166,235 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
Name: "main",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "service-resolver: envoy hash lb kitchen sink",
|
||||
snake: `
|
||||
kind = "service-resolver"
|
||||
name = "main"
|
||||
load_balancer = {
|
||||
envoy_lb_config = {
|
||||
policy = "ring_hash"
|
||||
ring_hash_config = {
|
||||
minimum_ring_size = 1
|
||||
maximum_ring_size = 2
|
||||
}
|
||||
hash_policies = [
|
||||
{
|
||||
field = "cookie"
|
||||
field_value = "good-cookie"
|
||||
cookie_config = {
|
||||
ttl = "1s"
|
||||
path = "/oven"
|
||||
}
|
||||
terminal = true
|
||||
},
|
||||
{
|
||||
field = "header"
|
||||
field_value = "x-user-id"
|
||||
},
|
||||
{
|
||||
source_ip = true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
`,
|
||||
camel: `
|
||||
Kind = "service-resolver"
|
||||
Name = "main"
|
||||
LoadBalancer = {
|
||||
EnvoyLBConfig = {
|
||||
Policy = "ring_hash"
|
||||
RingHashConfig = {
|
||||
MinimumRingSize = 1
|
||||
MaximumRingSize = 2
|
||||
}
|
||||
HashPolicies = [
|
||||
{
|
||||
Field = "cookie"
|
||||
FieldValue = "good-cookie"
|
||||
CookieConfig = {
|
||||
TTL = "1s"
|
||||
Path = "/oven"
|
||||
}
|
||||
Terminal = true
|
||||
},
|
||||
{
|
||||
Field = "header"
|
||||
FieldValue = "x-user-id"
|
||||
},
|
||||
{
|
||||
SourceIP = true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
`,
|
||||
snakeJSON: `
|
||||
{
|
||||
"kind": "service-resolver",
|
||||
"name": "main",
|
||||
"load_balancer": {
|
||||
"envoy_lb_config": {
|
||||
"policy": "ring_hash",
|
||||
"ring_hash_config": {
|
||||
"minimum_ring_size": 1,
|
||||
"maximum_ring_size": 2
|
||||
},
|
||||
"hash_policies": [
|
||||
{
|
||||
"field": "cookie",
|
||||
"field_value": "good-cookie",
|
||||
"cookie_config": {
|
||||
"ttl": "1s",
|
||||
"path": "/oven"
|
||||
},
|
||||
"terminal": true
|
||||
},
|
||||
{
|
||||
"field": "header",
|
||||
"field_value": "x-user-id"
|
||||
},
|
||||
{
|
||||
"source_ip": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
camelJSON: `
|
||||
{
|
||||
"Kind": "service-resolver",
|
||||
"Name": "main",
|
||||
"LoadBalancer": {
|
||||
"EnvoyLBConfig": {
|
||||
"Policy": "ring_hash",
|
||||
"RingHashConfig": {
|
||||
"MinimumRingSize": 1,
|
||||
"MaximumRingSize": 2
|
||||
},
|
||||
"HashPolicies": [
|
||||
{
|
||||
"Field": "cookie",
|
||||
"FieldValue": "good-cookie",
|
||||
"CookieConfig": {
|
||||
"TTL": "1s",
|
||||
"Path": "/oven"
|
||||
},
|
||||
"Terminal": true
|
||||
},
|
||||
{
|
||||
"Field": "header",
|
||||
"FieldValue": "x-user-id"
|
||||
},
|
||||
{
|
||||
"SourceIP": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
expect: &api.ServiceResolverConfigEntry{
|
||||
Kind: "service-resolver",
|
||||
Name: "main",
|
||||
LoadBalancer: &api.LoadBalancer{
|
||||
EnvoyLBConfig: &api.EnvoyLBConfig{
|
||||
Policy: structs.LBPolicyRingHash,
|
||||
RingHashConfig: &api.RingHashConfig{
|
||||
MinimumRingSize: 1,
|
||||
MaximumRingSize: 2,
|
||||
},
|
||||
HashPolicies: []api.HashPolicy{
|
||||
{
|
||||
Field: structs.HashPolicyCookie,
|
||||
FieldValue: "good-cookie",
|
||||
CookieConfig: &api.CookieConfig{
|
||||
TTL: 1 * time.Second,
|
||||
Path: "/oven",
|
||||
},
|
||||
Terminal: true,
|
||||
},
|
||||
{
|
||||
Field: structs.HashPolicyHeader,
|
||||
FieldValue: "x-user-id",
|
||||
},
|
||||
{
|
||||
SourceIP: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "service-resolver: envoy least request kitchen sink",
|
||||
snake: `
|
||||
kind = "service-resolver"
|
||||
name = "main"
|
||||
load_balancer = {
|
||||
envoy_lb_config = {
|
||||
policy = "least_request"
|
||||
least_request_config = {
|
||||
choice_count = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
camel: `
|
||||
Kind = "service-resolver"
|
||||
Name = "main"
|
||||
LoadBalancer = {
|
||||
EnvoyLBConfig = {
|
||||
Policy = "least_request"
|
||||
LeastRequestConfig = {
|
||||
ChoiceCount = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
snakeJSON: `
|
||||
{
|
||||
"kind": "service-resolver",
|
||||
"name": "main",
|
||||
"load_balancer": {
|
||||
"envoy_lb_config": {
|
||||
"policy": "least_request",
|
||||
"least_request_config": {
|
||||
"choice_count": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
camelJSON: `
|
||||
{
|
||||
"Kind": "service-resolver",
|
||||
"Name": "main",
|
||||
"LoadBalancer": {
|
||||
"EnvoyLBConfig": {
|
||||
"Policy": "least_request",
|
||||
"LeastRequestConfig": {
|
||||
"ChoiceCount": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
expect: &api.ServiceResolverConfigEntry{
|
||||
Kind: "service-resolver",
|
||||
Name: "main",
|
||||
LoadBalancer: &api.LoadBalancer{
|
||||
EnvoyLBConfig: &api.EnvoyLBConfig{
|
||||
Policy: structs.LBPolicyLeastRequest,
|
||||
LeastRequestConfig: &api.LeastRequestConfig{
|
||||
ChoiceCount: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "expose paths: kitchen sink proxy defaults",
|
||||
snake: `
|
||||
|
|
|
@ -83,7 +83,7 @@ LoadBalancer = {
|
|||
HashPolicies = [
|
||||
{
|
||||
Field = "header"
|
||||
FieldMatchValue = "x-user-id"
|
||||
FieldValue = "x-user-id"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -171,48 +171,52 @@ LoadBalancer = {
|
|||
configuration for services issuing requests to this upstream.
|
||||
This option is available in Consul versions 1.8.4 and newer.
|
||||
|
||||
**Note:** The options below are specific to Envoy proxy.
|
||||
|
||||
- `Policy` `(string: "")` - The load balancing policy used to select a host.
|
||||
One of: `random`, `round_robin`, `least_request`, `ring_hash`, `maglev`.
|
||||
|
||||
- `RingHashConfig` `(RingHashConfig)` - Configuration for the `ring_hash`
|
||||
policy type.
|
||||
|
||||
- `MinimumRingRize` `(int: 1024)` - Determines the minimum number of entries
|
||||
in the hash ring.
|
||||
|
||||
- `MaximumRingRize` `(int: 8192)` - Determines the maximum number of entries
|
||||
in the hash ring.
|
||||
|
||||
- `LeastRequestConfig` `(LeastRequestConfig)` - Configuration for the `least_request`
|
||||
policy type.
|
||||
|
||||
- `ChoiceCount` `(int: 2)` - Determines the number of random healthy hosts
|
||||
from which to select the one with the least requests.
|
||||
|
||||
- `HashPolicies` `(array<HashPolicies>)` - a list of hash policies to use for
|
||||
hashing load balancing algorithms. Hash policies are evaluated individually
|
||||
and combined such that identical lists result in the same hash.
|
||||
If no hash policies are present, or none are successfully evaluated,
|
||||
then a random backend host will be selected.
|
||||
|
||||
- `Field` `(string: "")` - The attribute type to hash on.
|
||||
Must be one of `header`,`cookie`, or `query_parameter`.
|
||||
Cannot be specified along with `SourceAddress`.
|
||||
- `EnvoyLBConfig` `(EnvoyLBConfig)` - Envoy proxy specific load balancing configuration
|
||||
for this upstream.
|
||||
|
||||
- `Policy` `(string: "")` - The load balancing policy used to select a host.
|
||||
One of: `random`, `round_robin`, `least_request`, `ring_hash`, `maglev`.
|
||||
|
||||
- `RingHashConfig` `(RingHashConfig)` - Configuration for the `ring_hash`
|
||||
policy type.
|
||||
|
||||
- `FieldMatchValue` `(string: "")` - The value to hash.
|
||||
ie. header name, cookie name, URL query parameter name.
|
||||
Cannot be specified along with `SourceAddress`.
|
||||
- `MinimumRingRize` `(int: 1024)` - Determines the minimum number of entries
|
||||
in the hash ring.
|
||||
|
||||
- `SourceAddress` `(bool: false)` - Determines whether the hash should be of the source IP
|
||||
address rather than of a field and field value.
|
||||
Cannot be specified along with `Field` or `FieldMatchValue`.
|
||||
- `MaximumRingRize` `(int: 8192)` - Determines the maximum number of entries
|
||||
in the hash ring.
|
||||
|
||||
- `LeastRequestConfig` `(LeastRequestConfig)` - Configuration for the `least_request`
|
||||
policy type.
|
||||
|
||||
- `Terminal` `(bool: false)` - Will short circuit the computation of the hash
|
||||
when multiple hash policies are present. If a hash is computed when a
|
||||
Terminal policy is evaluated, then that hash will be used and subsequent
|
||||
hash policies will be ignored.
|
||||
- `ChoiceCount` `(int: 2)` - Determines the number of random healthy hosts
|
||||
from which to select the one with the least requests.
|
||||
|
||||
- `HashPolicies` `(array<HashPolicies>)` - a list of hash policies to use for
|
||||
hashing load balancing algorithms. Hash policies are evaluated individually
|
||||
and combined such that identical lists result in the same hash.
|
||||
If no hash policies are present, or none are successfully evaluated,
|
||||
then a random backend host will be selected.
|
||||
|
||||
- `Field` `(string: "")` - The attribute type to hash on.
|
||||
Must be one of `header`,`cookie`, or `query_parameter`.
|
||||
Cannot be specified along with `SourceAddress`.
|
||||
|
||||
- `FieldValue` `(string: "")` - The value to hash.
|
||||
ie. header name, cookie name, URL query parameter name.
|
||||
Cannot be specified along with `SourceAddress`.
|
||||
|
||||
- `CookieConfig` `(CookieConfig)` - Additional configuration for the "cookie" hash policy type.
|
||||
This is specified to have Envoy generate a cookie for a client on its first request.
|
||||
|
||||
- `SourceIP` `(bool: false)` - Determines whether the hash should be of the source IP
|
||||
address rather than of a field and field value.
|
||||
Cannot be specified along with `Field` or `FieldValue`.
|
||||
|
||||
- `Terminal` `(bool: false)` - Will short circuit the computation of the hash
|
||||
when multiple hash policies are present. If a hash is computed when a
|
||||
Terminal policy is evaluated, then that hash will be used and subsequent
|
||||
hash policies will be ignored.
|
||||
|
||||
## Service Subsets
|
||||
|
||||
|
|
|
@ -184,6 +184,12 @@ A single node in the compiled discovery chain.
|
|||
|
||||
- `Targets` `(array<string>)` - List of targets found in
|
||||
[`Targets`](#targets) to failover to in order of preference.
|
||||
|
||||
- `LoadBalancer` `(LoadBalancer: <optional>`) - Copy of the underlying `service-resolver`
|
||||
[`LoadBalancer`](/docs/agent/config-entries/service-resolver#loadbalancer) field.
|
||||
|
||||
If a `service-splitter` splits between services with differing `LoadBalancer` configuration
|
||||
the first hash-based load balancing policy is copied.
|
||||
|
||||
#### `DiscoveryTarget`
|
||||
|
||||
|
|
Loading…
Reference in New Issue