From 63f79e5f9b84989cc313d3c8a39f433d0de5be64 Mon Sep 17 00:00:00 2001 From: freddygv Date: Wed, 2 Sep 2020 09:10:50 -0600 Subject: [PATCH] Restructure structs and other PR comments --- agent/consul/discoverychain/compile.go | 8 +- agent/consul/discoverychain/compile_test.go | 168 +++--- agent/proxycfg/testing.go | 38 +- agent/structs/config_entry_discoverychain.go | 277 +++++++--- .../config_entry_discoverychain_test.go | 507 +++++++++++++++--- agent/structs/discovery_chain.go | 2 +- agent/xds/clusters.go | 66 +-- agent/xds/clusters_test.go | 118 +--- agent/xds/routes.go | 95 +--- agent/xds/routes_test.go | 214 +------- ...ignore-extra-resolvers.envoy-1-12-x.golden | 32 -- ...ignore-extra-resolvers.envoy-1-13-x.golden | 32 -- ...ignore-extra-resolvers.envoy-1-14-x.golden | 32 -- ...ignore-extra-resolvers.envoy-1-15-x.golden | 32 -- ...ateway-service-subsets.envoy-1-12-x.golden | 32 -- ...ateway-service-subsets.envoy-1-13-x.golden | 32 -- ...ateway-service-subsets.envoy-1-14-x.golden | 32 -- ...ateway-service-subsets.envoy-1-15-x.golden | 32 -- ...teway-service-timeouts.envoy-1-12-x.golden | 34 +- ...teway-service-timeouts.envoy-1-13-x.golden | 34 +- ...teway-service-timeouts.envoy-1-14-x.golden | 34 +- ...teway-service-timeouts.envoy-1-15-x.golden | 34 +- ...stname-service-subsets.envoy-1-12-x.golden | 86 --- ...stname-service-subsets.envoy-1-13-x.golden | 86 --- ...stname-service-subsets.envoy-1-14-x.golden | 86 --- ...stname-service-subsets.envoy-1-15-x.golden | 86 --- ...ignore-extra-resolvers.envoy-1-12-x.golden | 56 -- ...ignore-extra-resolvers.envoy-1-13-x.golden | 56 -- ...ignore-extra-resolvers.envoy-1-14-x.golden | 56 -- ...ignore-extra-resolvers.envoy-1-15-x.golden | 56 -- ...ateway-service-subsets.envoy-1-12-x.golden | 88 --- ...ateway-service-subsets.envoy-1-13-x.golden | 88 --- ...ateway-service-subsets.envoy-1-14-x.golden | 88 --- ...ateway-service-subsets.envoy-1-15-x.golden | 88 --- ...ting-gateway-lb-config.envoy-1-12-x.golden | 75 +-- ...ting-gateway-lb-config.envoy-1-13-x.golden | 75 +-- ...ting-gateway-lb-config.envoy-1-14-x.golden | 75 +-- ...ting-gateway-lb-config.envoy-1-15-x.golden | 75 +-- api/config_entry_discoverychain.go | 43 +- api/config_entry_discoverychain_test.go | 44 +- command/config/write/config_write_test.go | 230 ++++++++ .../agent/config-entries/service-resolver.mdx | 84 +-- .../pages/docs/internals/discovery-chain.mdx | 6 + 43 files changed, 1228 insertions(+), 2284 deletions(-) diff --git a/agent/consul/discoverychain/compile.go b/agent/consul/discoverychain/compile.go index d946677870..31c3baa967 100644 --- a/agent/consul/discoverychain/compile.go +++ b/agent/consul/discoverychain/compile.go @@ -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 + } } } diff --git a/agent/consul/discoverychain/compile_test.go b/agent/consul/discoverychain/compile_test.go index e5aca02b4a..4204362723 100644 --- a/agent/consul/discoverychain/compile_test.go +++ b/agent/consul/discoverychain/compile_test.go @@ -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, + }, }, }, }, diff --git a/agent/proxycfg/testing.go b/agent/proxycfg/testing.go index 96a4c8749f..0ed1acd12b 100644 --- a/agent/proxycfg/testing.go +++ b/agent/proxycfg/testing.go @@ -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, + }, }, }, }, diff --git a/agent/structs/config_entry_discoverychain.go b/agent/structs/config_entry_discoverychain.go index 79a33cb48a..e033f674fb 100644 --- a/agent/structs/config_entry_discoverychain.go +++ b/agent/structs/config_entry_discoverychain.go @@ -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 diff --git a/agent/structs/config_entry_discoverychain_test.go b/agent/structs/config_entry_discoverychain_test.go index d5db08ec52..bd323855c0 100644 --- a/agent/structs/config_entry_discoverychain_test.go +++ b/agent/structs/config_entry_discoverychain_test.go @@ -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) + }) + } +} diff --git a/agent/structs/discovery_chain.go b/agent/structs/discovery_chain.go index 85ee5965cb..77eb03937c 100644 --- a/agent/structs/discovery_chain.go +++ b/agent/structs/discovery_chain.go @@ -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 { diff --git a/agent/xds/clusters.go b/agent/xds/clusters.go index 8bad63b63f..b872432128 100644 --- a/agent/xds/clusters.go +++ b/agent/xds/clusters.go @@ -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. // diff --git a/agent/xds/clusters_test.go b/agent/xds/clusters_test.go index 14714feb7b..634cbe54c8 100644 --- a/agent/xds/clusters_test.go +++ b/agent/xds/clusters_test.go @@ -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) - }) - } -} diff --git a/agent/xds/routes.go b/agent/xds/routes.go index f7f991f7e6..bf1f5cc3a6 100644 --- a/agent/xds/routes.go +++ b/agent/xds/routes.go @@ -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() { diff --git a/agent/xds/routes_test.go b/agent/xds/routes_test.go index 7142ee4452..88020b247b 100644 --- a/agent/xds/routes_test.go +++ b/agent/xds/routes_test.go @@ -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) - }) - } -} diff --git a/agent/xds/testdata/clusters/mesh-gateway-ignore-extra-resolvers.envoy-1-12-x.golden b/agent/xds/testdata/clusters/mesh-gateway-ignore-extra-resolvers.envoy-1-12-x.golden index afc23f9ae1..845881fd3f 100644 --- a/agent/xds/testdata/clusters/mesh-gateway-ignore-extra-resolvers.envoy-1-12-x.golden +++ b/agent/xds/testdata/clusters/mesh-gateway-ignore-extra-resolvers.envoy-1-12-x.golden @@ -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": { - } } ], diff --git a/agent/xds/testdata/clusters/mesh-gateway-ignore-extra-resolvers.envoy-1-13-x.golden b/agent/xds/testdata/clusters/mesh-gateway-ignore-extra-resolvers.envoy-1-13-x.golden index afc23f9ae1..845881fd3f 100644 --- a/agent/xds/testdata/clusters/mesh-gateway-ignore-extra-resolvers.envoy-1-13-x.golden +++ b/agent/xds/testdata/clusters/mesh-gateway-ignore-extra-resolvers.envoy-1-13-x.golden @@ -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": { - } } ], diff --git a/agent/xds/testdata/clusters/mesh-gateway-ignore-extra-resolvers.envoy-1-14-x.golden b/agent/xds/testdata/clusters/mesh-gateway-ignore-extra-resolvers.envoy-1-14-x.golden index afc23f9ae1..845881fd3f 100644 --- a/agent/xds/testdata/clusters/mesh-gateway-ignore-extra-resolvers.envoy-1-14-x.golden +++ b/agent/xds/testdata/clusters/mesh-gateway-ignore-extra-resolvers.envoy-1-14-x.golden @@ -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": { - } } ], diff --git a/agent/xds/testdata/clusters/mesh-gateway-ignore-extra-resolvers.envoy-1-15-x.golden b/agent/xds/testdata/clusters/mesh-gateway-ignore-extra-resolvers.envoy-1-15-x.golden index afc23f9ae1..845881fd3f 100644 --- a/agent/xds/testdata/clusters/mesh-gateway-ignore-extra-resolvers.envoy-1-15-x.golden +++ b/agent/xds/testdata/clusters/mesh-gateway-ignore-extra-resolvers.envoy-1-15-x.golden @@ -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": { - } } ], diff --git a/agent/xds/testdata/clusters/mesh-gateway-service-subsets.envoy-1-12-x.golden b/agent/xds/testdata/clusters/mesh-gateway-service-subsets.envoy-1-12-x.golden index afc23f9ae1..845881fd3f 100644 --- a/agent/xds/testdata/clusters/mesh-gateway-service-subsets.envoy-1-12-x.golden +++ b/agent/xds/testdata/clusters/mesh-gateway-service-subsets.envoy-1-12-x.golden @@ -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": { - } } ], diff --git a/agent/xds/testdata/clusters/mesh-gateway-service-subsets.envoy-1-13-x.golden b/agent/xds/testdata/clusters/mesh-gateway-service-subsets.envoy-1-13-x.golden index afc23f9ae1..845881fd3f 100644 --- a/agent/xds/testdata/clusters/mesh-gateway-service-subsets.envoy-1-13-x.golden +++ b/agent/xds/testdata/clusters/mesh-gateway-service-subsets.envoy-1-13-x.golden @@ -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": { - } } ], diff --git a/agent/xds/testdata/clusters/mesh-gateway-service-subsets.envoy-1-14-x.golden b/agent/xds/testdata/clusters/mesh-gateway-service-subsets.envoy-1-14-x.golden index afc23f9ae1..845881fd3f 100644 --- a/agent/xds/testdata/clusters/mesh-gateway-service-subsets.envoy-1-14-x.golden +++ b/agent/xds/testdata/clusters/mesh-gateway-service-subsets.envoy-1-14-x.golden @@ -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": { - } } ], diff --git a/agent/xds/testdata/clusters/mesh-gateway-service-subsets.envoy-1-15-x.golden b/agent/xds/testdata/clusters/mesh-gateway-service-subsets.envoy-1-15-x.golden index afc23f9ae1..845881fd3f 100644 --- a/agent/xds/testdata/clusters/mesh-gateway-service-subsets.envoy-1-15-x.golden +++ b/agent/xds/testdata/clusters/mesh-gateway-service-subsets.envoy-1-15-x.golden @@ -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": { - } } ], diff --git a/agent/xds/testdata/clusters/mesh-gateway-service-timeouts.envoy-1-12-x.golden b/agent/xds/testdata/clusters/mesh-gateway-service-timeouts.envoy-1-12-x.golden index bf2d501422..845881fd3f 100644 --- a/agent/xds/testdata/clusters/mesh-gateway-service-timeouts.envoy-1-12-x.golden +++ b/agent/xds/testdata/clusters/mesh-gateway-service-timeouts.envoy-1-12-x.golden @@ -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": { - } } ], diff --git a/agent/xds/testdata/clusters/mesh-gateway-service-timeouts.envoy-1-13-x.golden b/agent/xds/testdata/clusters/mesh-gateway-service-timeouts.envoy-1-13-x.golden index bf2d501422..845881fd3f 100644 --- a/agent/xds/testdata/clusters/mesh-gateway-service-timeouts.envoy-1-13-x.golden +++ b/agent/xds/testdata/clusters/mesh-gateway-service-timeouts.envoy-1-13-x.golden @@ -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": { - } } ], diff --git a/agent/xds/testdata/clusters/mesh-gateway-service-timeouts.envoy-1-14-x.golden b/agent/xds/testdata/clusters/mesh-gateway-service-timeouts.envoy-1-14-x.golden index bf2d501422..845881fd3f 100644 --- a/agent/xds/testdata/clusters/mesh-gateway-service-timeouts.envoy-1-14-x.golden +++ b/agent/xds/testdata/clusters/mesh-gateway-service-timeouts.envoy-1-14-x.golden @@ -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": { - } } ], diff --git a/agent/xds/testdata/clusters/mesh-gateway-service-timeouts.envoy-1-15-x.golden b/agent/xds/testdata/clusters/mesh-gateway-service-timeouts.envoy-1-15-x.golden index bf2d501422..845881fd3f 100644 --- a/agent/xds/testdata/clusters/mesh-gateway-service-timeouts.envoy-1-15-x.golden +++ b/agent/xds/testdata/clusters/mesh-gateway-service-timeouts.envoy-1-15-x.golden @@ -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": { - } } ], diff --git a/agent/xds/testdata/clusters/terminating-gateway-hostname-service-subsets.envoy-1-12-x.golden b/agent/xds/testdata/clusters/terminating-gateway-hostname-service-subsets.envoy-1-12-x.golden index 44bd0fd5f0..27b1ddc6c7 100644 --- a/agent/xds/testdata/clusters/terminating-gateway-hostname-service-subsets.envoy-1-12-x.golden +++ b/agent/xds/testdata/clusters/terminating-gateway-hostname-service-subsets.envoy-1-12-x.golden @@ -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", diff --git a/agent/xds/testdata/clusters/terminating-gateway-hostname-service-subsets.envoy-1-13-x.golden b/agent/xds/testdata/clusters/terminating-gateway-hostname-service-subsets.envoy-1-13-x.golden index 44bd0fd5f0..27b1ddc6c7 100644 --- a/agent/xds/testdata/clusters/terminating-gateway-hostname-service-subsets.envoy-1-13-x.golden +++ b/agent/xds/testdata/clusters/terminating-gateway-hostname-service-subsets.envoy-1-13-x.golden @@ -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", diff --git a/agent/xds/testdata/clusters/terminating-gateway-hostname-service-subsets.envoy-1-14-x.golden b/agent/xds/testdata/clusters/terminating-gateway-hostname-service-subsets.envoy-1-14-x.golden index 44bd0fd5f0..27b1ddc6c7 100644 --- a/agent/xds/testdata/clusters/terminating-gateway-hostname-service-subsets.envoy-1-14-x.golden +++ b/agent/xds/testdata/clusters/terminating-gateway-hostname-service-subsets.envoy-1-14-x.golden @@ -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", diff --git a/agent/xds/testdata/clusters/terminating-gateway-hostname-service-subsets.envoy-1-15-x.golden b/agent/xds/testdata/clusters/terminating-gateway-hostname-service-subsets.envoy-1-15-x.golden index 44bd0fd5f0..27b1ddc6c7 100644 --- a/agent/xds/testdata/clusters/terminating-gateway-hostname-service-subsets.envoy-1-15-x.golden +++ b/agent/xds/testdata/clusters/terminating-gateway-hostname-service-subsets.envoy-1-15-x.golden @@ -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", diff --git a/agent/xds/testdata/clusters/terminating-gateway-ignore-extra-resolvers.envoy-1-12-x.golden b/agent/xds/testdata/clusters/terminating-gateway-ignore-extra-resolvers.envoy-1-12-x.golden index f9c7336e6f..27b1ddc6c7 100644 --- a/agent/xds/testdata/clusters/terminating-gateway-ignore-extra-resolvers.envoy-1-12-x.golden +++ b/agent/xds/testdata/clusters/terminating-gateway-ignore-extra-resolvers.envoy-1-12-x.golden @@ -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", diff --git a/agent/xds/testdata/clusters/terminating-gateway-ignore-extra-resolvers.envoy-1-13-x.golden b/agent/xds/testdata/clusters/terminating-gateway-ignore-extra-resolvers.envoy-1-13-x.golden index f9c7336e6f..27b1ddc6c7 100644 --- a/agent/xds/testdata/clusters/terminating-gateway-ignore-extra-resolvers.envoy-1-13-x.golden +++ b/agent/xds/testdata/clusters/terminating-gateway-ignore-extra-resolvers.envoy-1-13-x.golden @@ -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", diff --git a/agent/xds/testdata/clusters/terminating-gateway-ignore-extra-resolvers.envoy-1-14-x.golden b/agent/xds/testdata/clusters/terminating-gateway-ignore-extra-resolvers.envoy-1-14-x.golden index f9c7336e6f..27b1ddc6c7 100644 --- a/agent/xds/testdata/clusters/terminating-gateway-ignore-extra-resolvers.envoy-1-14-x.golden +++ b/agent/xds/testdata/clusters/terminating-gateway-ignore-extra-resolvers.envoy-1-14-x.golden @@ -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", diff --git a/agent/xds/testdata/clusters/terminating-gateway-ignore-extra-resolvers.envoy-1-15-x.golden b/agent/xds/testdata/clusters/terminating-gateway-ignore-extra-resolvers.envoy-1-15-x.golden index f9c7336e6f..27b1ddc6c7 100644 --- a/agent/xds/testdata/clusters/terminating-gateway-ignore-extra-resolvers.envoy-1-15-x.golden +++ b/agent/xds/testdata/clusters/terminating-gateway-ignore-extra-resolvers.envoy-1-15-x.golden @@ -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", diff --git a/agent/xds/testdata/clusters/terminating-gateway-service-subsets.envoy-1-12-x.golden b/agent/xds/testdata/clusters/terminating-gateway-service-subsets.envoy-1-12-x.golden index 8e3db04606..27b1ddc6c7 100644 --- a/agent/xds/testdata/clusters/terminating-gateway-service-subsets.envoy-1-12-x.golden +++ b/agent/xds/testdata/clusters/terminating-gateway-service-subsets.envoy-1-12-x.golden @@ -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", diff --git a/agent/xds/testdata/clusters/terminating-gateway-service-subsets.envoy-1-13-x.golden b/agent/xds/testdata/clusters/terminating-gateway-service-subsets.envoy-1-13-x.golden index 8e3db04606..27b1ddc6c7 100644 --- a/agent/xds/testdata/clusters/terminating-gateway-service-subsets.envoy-1-13-x.golden +++ b/agent/xds/testdata/clusters/terminating-gateway-service-subsets.envoy-1-13-x.golden @@ -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", diff --git a/agent/xds/testdata/clusters/terminating-gateway-service-subsets.envoy-1-14-x.golden b/agent/xds/testdata/clusters/terminating-gateway-service-subsets.envoy-1-14-x.golden index 8e3db04606..27b1ddc6c7 100644 --- a/agent/xds/testdata/clusters/terminating-gateway-service-subsets.envoy-1-14-x.golden +++ b/agent/xds/testdata/clusters/terminating-gateway-service-subsets.envoy-1-14-x.golden @@ -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", diff --git a/agent/xds/testdata/clusters/terminating-gateway-service-subsets.envoy-1-15-x.golden b/agent/xds/testdata/clusters/terminating-gateway-service-subsets.envoy-1-15-x.golden index 8e3db04606..27b1ddc6c7 100644 --- a/agent/xds/testdata/clusters/terminating-gateway-service-subsets.envoy-1-15-x.golden +++ b/agent/xds/testdata/clusters/terminating-gateway-service-subsets.envoy-1-15-x.golden @@ -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", diff --git a/agent/xds/testdata/routes/terminating-gateway-lb-config.envoy-1-12-x.golden b/agent/xds/testdata/routes/terminating-gateway-lb-config.envoy-1-12-x.golden index b611e2508d..e8370f2657 100644 --- a/agent/xds/testdata/routes/terminating-gateway-lb-config.envoy-1-12-x.golden +++ b/agent/xds/testdata/routes/terminating-gateway-lb-config.envoy-1-12-x.golden @@ -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" } } ] diff --git a/agent/xds/testdata/routes/terminating-gateway-lb-config.envoy-1-13-x.golden b/agent/xds/testdata/routes/terminating-gateway-lb-config.envoy-1-13-x.golden index b611e2508d..e8370f2657 100644 --- a/agent/xds/testdata/routes/terminating-gateway-lb-config.envoy-1-13-x.golden +++ b/agent/xds/testdata/routes/terminating-gateway-lb-config.envoy-1-13-x.golden @@ -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" } } ] diff --git a/agent/xds/testdata/routes/terminating-gateway-lb-config.envoy-1-14-x.golden b/agent/xds/testdata/routes/terminating-gateway-lb-config.envoy-1-14-x.golden index b611e2508d..e8370f2657 100644 --- a/agent/xds/testdata/routes/terminating-gateway-lb-config.envoy-1-14-x.golden +++ b/agent/xds/testdata/routes/terminating-gateway-lb-config.envoy-1-14-x.golden @@ -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" } } ] diff --git a/agent/xds/testdata/routes/terminating-gateway-lb-config.envoy-1-15-x.golden b/agent/xds/testdata/routes/terminating-gateway-lb-config.envoy-1-15-x.golden index b611e2508d..e8370f2657 100644 --- a/agent/xds/testdata/routes/terminating-gateway-lb-config.envoy-1-15-x.golden +++ b/agent/xds/testdata/routes/terminating-gateway-lb-config.envoy-1-15-x.golden @@ -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" } } ] diff --git a/api/config_entry_discoverychain.go b/api/config_entry_discoverychain.go index 5e1636fe83..68546b615a 100644 --- a/api/config_entry_discoverychain.go +++ b/api/config_entry_discoverychain.go @@ -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"` +} diff --git a/api/config_entry_discoverychain_test.go b/api/config_entry_discoverychain_test.go index 0e77429bb6..560dc1e24c 100644 --- a/api/config_entry_discoverychain_test.go +++ b/api/config_entry_discoverychain_test.go @@ -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, + }, }, }, }, diff --git a/command/config/write/config_write_test.go b/command/config/write/config_write_test.go index a5b9120b29..82bbda4bb5 100644 --- a/command/config/write/config_write_test.go +++ b/command/config/write/config_write_test.go @@ -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: ` diff --git a/website/pages/docs/agent/config-entries/service-resolver.mdx b/website/pages/docs/agent/config-entries/service-resolver.mdx index d0cd549888..c5a27b5335 100644 --- a/website/pages/docs/agent/config-entries/service-resolver.mdx +++ b/website/pages/docs/agent/config-entries/service-resolver.mdx @@ -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)` - 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)` - 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 diff --git a/website/pages/docs/internals/discovery-chain.mdx b/website/pages/docs/internals/discovery-chain.mdx index 9c0ec3bb88..f42d52bb22 100644 --- a/website/pages/docs/internals/discovery-chain.mdx +++ b/website/pages/docs/internals/discovery-chain.mdx @@ -184,6 +184,12 @@ A single node in the compiled discovery chain. - `Targets` `(array)` - List of targets found in [`Targets`](#targets) to failover to in order of preference. + + - `LoadBalancer` `(LoadBalancer: `) - 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`