Header manip for split legs plumbing

This commit is contained in:
Paul Banks 2021-07-13 19:49:14 +01:00
parent f70f7b2389
commit 1dd1683ed9
9 changed files with 325 additions and 22 deletions

View File

@ -417,8 +417,12 @@ func (c *compiler) flattenAdjacentSplitterNodes() {
effectiveWeight := split.Weight * innerSplit.Weight / 100
newDiscoverySplit := &structs.DiscoverySplit{
Weight: structs.NormalizeServiceSplitWeight(effectiveWeight),
NextNode: innerSplit.NextNode,
// Copy the definition from the inner node so any extra config (e.g.
// header manipulation) will be applied to requests taking this
// path.
Definition: innerSplit.Definition,
Weight: structs.NormalizeServiceSplitWeight(effectiveWeight),
NextNode: innerSplit.NextNode,
}
fixedSplits = append(fixedSplits, newDiscoverySplit)
@ -723,9 +727,16 @@ func (c *compiler) getSplitterNode(sid structs.ServiceID) (*structs.DiscoveryGra
c.recordNode(splitNode)
var hasLB bool
for _, split := range splitter.Splits {
for i := range splitter.Splits {
// We don't use range variables here because we'll take the address of
// this split and store that in a DiscoveryGraphNode and the range
// variables share memory addresses between iterations which is exactly
// wrong for us here.
split := splitter.Splits[i]
compiledSplit := &structs.DiscoverySplit{
Weight: split.Weight,
Definition: &split,
Weight: split.Weight,
}
splitNode.Splits = append(splitNode.Splits, compiledSplit)

View File

@ -1040,9 +1040,36 @@ func setupTestVariationConfigEntriesAndSnapshot(
Kind: structs.ServiceSplitter,
Name: "db",
Splits: []structs.ServiceSplit{
{Weight: 95.5, Service: "big-side"},
{Weight: 4, Service: "goldilocks-side"},
{Weight: 0.5, Service: "lil-bit-side"},
{
Weight: 95.5,
Service: "big-side",
RequestHeaders: &structs.HTTPHeaderModifiers{
Set: map[string]string{"x-split-leg": "big"},
},
ResponseHeaders: &structs.HTTPHeaderModifiers{
Set: map[string]string{"x-split-leg": "big"},
},
},
{
Weight: 4,
Service: "goldilocks-side",
RequestHeaders: &structs.HTTPHeaderModifiers{
Set: map[string]string{"x-split-leg": "goldilocks"},
},
ResponseHeaders: &structs.HTTPHeaderModifiers{
Set: map[string]string{"x-split-leg": "goldilocks"},
},
},
{
Weight: 0.5,
Service: "lil-bit-side",
RequestHeaders: &structs.HTTPHeaderModifiers{
Set: map[string]string{"x-split-leg": "small"},
},
ResponseHeaders: &structs.HTTPHeaderModifiers{
Set: map[string]string{"x-split-leg": "small"},
},
},
},
},
)

View File

@ -1490,12 +1490,19 @@ type HTTPHeaderModifiers struct {
Remove []string `json:",omitempty"`
}
func (m *HTTPHeaderModifiers) IsZero() bool {
if m == nil {
return true
}
return len(m.Add) == 0 && len(m.Set) == 0 && len(m.Remove) == 0
}
func (m *HTTPHeaderModifiers) Validate(protocol string) error {
if m == nil {
// Empty is always valid
return nil
}
if len(m.Add) == 0 && len(m.Set) == 0 && len(m.Remove) == 0 {
if m.IsZero() {
return nil
}
if !IsProtocolHTTPLike(protocol) {

View File

@ -192,6 +192,13 @@ type DiscoveryRoute struct {
// compiled form of ServiceSplit
type DiscoverySplit struct {
Definition *ServiceSplit `json:",omitempty"`
// Weight is not necessarily a duplicate of Definition.Weight since when
// multiple splits are compiled down to a single set of splits the effective
// weight of a split leg might not be the same as in the original definition.
// Proxies should use this compiled weight. The Definition is provided above
// for any other significant configuration that the proxy might need to apply
// to that leg of the split.
Weight float32 `json:",omitempty"`
NextNode string `json:",omitempty"`
}

View File

@ -633,6 +633,9 @@ func makeRouteActionForSplitter(splits []*structs.DiscoverySplit, chain *structs
Weight: makeUint32Value(int(split.Weight * 100)),
Name: clusterName,
}
if err := injectHeaderManipToWeightedCluster(split.Definition, cw); err != nil {
return nil, err
}
clusters = append(clusters, cw)
}
@ -719,7 +722,7 @@ func injectLBToRouteAction(lb *structs.LoadBalancer, action *envoy_route_v3.Rout
}
func injectHeaderManipToRoute(dest *structs.ServiceRouteDestination, r *envoy_route_v3.Route) error {
if dest.RequestHeaders != nil {
if !dest.RequestHeaders.IsZero() {
r.RequestHeadersToAdd = append(
r.RequestHeadersToAdd,
makeHeadersValueOptions(dest.RequestHeaders.Add, true)...,
@ -733,7 +736,7 @@ func injectHeaderManipToRoute(dest *structs.ServiceRouteDestination, r *envoy_ro
dest.RequestHeaders.Remove...,
)
}
if dest.ResponseHeaders != nil {
if !dest.ResponseHeaders.IsZero() {
r.ResponseHeadersToAdd = append(
r.ResponseHeadersToAdd,
makeHeadersValueOptions(dest.ResponseHeaders.Add, true)...,
@ -749,3 +752,35 @@ func injectHeaderManipToRoute(dest *structs.ServiceRouteDestination, r *envoy_ro
}
return nil
}
func injectHeaderManipToWeightedCluster(split *structs.ServiceSplit, c *envoy_route_v3.WeightedCluster_ClusterWeight) error {
if !split.RequestHeaders.IsZero() {
c.RequestHeadersToAdd = append(
c.RequestHeadersToAdd,
makeHeadersValueOptions(split.RequestHeaders.Add, true)...,
)
c.RequestHeadersToAdd = append(
c.RequestHeadersToAdd,
makeHeadersValueOptions(split.RequestHeaders.Set, false)...,
)
c.RequestHeadersToRemove = append(
c.RequestHeadersToRemove,
split.RequestHeaders.Remove...,
)
}
if !split.ResponseHeaders.IsZero() {
c.ResponseHeadersToAdd = append(
c.ResponseHeadersToAdd,
makeHeadersValueOptions(split.ResponseHeaders.Add, true)...,
)
c.ResponseHeadersToAdd = append(
c.ResponseHeadersToAdd,
makeHeadersValueOptions(split.ResponseHeaders.Set, false)...,
)
c.ResponseHeadersToRemove = append(
c.ResponseHeadersToRemove,
split.ResponseHeaders.Remove...,
)
}
return nil
}

View File

@ -20,15 +20,69 @@
"clusters": [
{
"name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"weight": 9550
"weight": 9550,
"requestHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "big"
},
"append": false
}
],
"responseHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "big"
},
"append": false
}
]
},
{
"name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"weight": 400
"weight": 400,
"requestHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "goldilocks"
},
"append": false
}
],
"responseHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "goldilocks"
},
"append": false
}
]
},
{
"name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"weight": 50
"weight": 50,
"requestHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "small"
},
"append": false
}
],
"responseHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "small"
},
"append": false
}
]
}
],
"totalWeight": 10000

View File

@ -20,15 +20,69 @@
"clusters": [
{
"name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"weight": 9550
"weight": 9550,
"requestHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "big"
},
"append": false
}
],
"responseHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "big"
},
"append": false
}
]
},
{
"name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"weight": 400
"weight": 400,
"requestHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "goldilocks"
},
"append": false
}
],
"responseHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "goldilocks"
},
"append": false
}
]
},
{
"name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"weight": 50
"weight": 50,
"requestHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "small"
},
"append": false
}
],
"responseHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "small"
},
"append": false
}
]
}
],
"totalWeight": 10000

View File

@ -21,15 +21,69 @@
"clusters": [
{
"name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"weight": 9550
"weight": 9550,
"requestHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "big"
},
"append": false
}
],
"responseHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "big"
},
"append": false
}
]
},
{
"name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"weight": 400
"weight": 400,
"requestHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "goldilocks"
},
"append": false
}
],
"responseHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "goldilocks"
},
"append": false
}
]
},
{
"name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"weight": 50
"weight": 50,
"requestHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "small"
},
"append": false
}
],
"responseHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "small"
},
"append": false
}
]
}
],
"totalWeight": 10000

View File

@ -21,15 +21,69 @@
"clusters": [
{
"name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"weight": 9550
"weight": 9550,
"requestHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "big"
},
"append": false
}
],
"responseHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "big"
},
"append": false
}
]
},
{
"name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"weight": 400
"weight": 400,
"requestHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "goldilocks"
},
"append": false
}
],
"responseHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "goldilocks"
},
"append": false
}
]
},
{
"name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"weight": 50
"weight": 50,
"requestHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "small"
},
"append": false
}
],
"responseHeadersToAdd": [
{
"header": {
"key": "x-split-leg",
"value": "small"
},
"append": false
}
]
}
],
"totalWeight": 10000