2023-08-17 18:43:21 +00:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
|
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
|
2023-08-15 18:57:07 +00:00
|
|
|
package xdsv2
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2023-09-07 19:03:09 +00:00
|
|
|
"strings"
|
|
|
|
|
2023-08-17 21:04:53 +00:00
|
|
|
envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
|
|
|
|
envoy_matcher_v3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3"
|
2023-09-07 19:03:09 +00:00
|
|
|
"google.golang.org/protobuf/types/known/wrapperspb"
|
|
|
|
|
2023-08-17 21:04:53 +00:00
|
|
|
"github.com/hashicorp/consul/agent/xds/response"
|
|
|
|
"github.com/hashicorp/consul/envoyextensions/xdscommon"
|
2023-09-22 16:51:15 +00:00
|
|
|
"github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate"
|
2023-08-15 18:57:07 +00:00
|
|
|
|
|
|
|
envoy_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
|
|
|
|
)
|
|
|
|
|
2023-08-17 21:04:53 +00:00
|
|
|
func (pr *ProxyResources) makeEnvoyRoute(name string) (*envoy_route_v3.RouteConfiguration, error) {
|
2023-08-15 18:57:07 +00:00
|
|
|
var route *envoy_route_v3.RouteConfiguration
|
|
|
|
// TODO(proxystate): This will make routes in the future. This function should distinguish between static routes
|
|
|
|
// inlined into listeners and non-static routes that should be added as top level Envoy resources.
|
|
|
|
_, ok := pr.proxyState.Routes[name]
|
|
|
|
if !ok {
|
|
|
|
// This should not happen with a valid proxy state.
|
|
|
|
return nil, fmt.Errorf("could not find route in ProxyState: %s", name)
|
|
|
|
}
|
|
|
|
return route, nil
|
|
|
|
}
|
2023-08-17 21:04:53 +00:00
|
|
|
|
|
|
|
// makeEnvoyRouteConfigFromProxystateRoute converts the proxystate representation of a Route into Envoy proto message
|
|
|
|
// form. We don't throw any errors here, since the proxystate has already been validated.
|
|
|
|
func (pr *ProxyResources) makeEnvoyRouteConfigFromProxystateRoute(name string, psRoute *pbproxystate.Route) *envoy_route_v3.RouteConfiguration {
|
|
|
|
envoyRouteConfig := &envoy_route_v3.RouteConfiguration{
|
|
|
|
Name: name,
|
|
|
|
// ValidateClusters defaults to true when defined statically and false
|
|
|
|
// when done via RDS. Re-set the reasonable value of true to prevent
|
|
|
|
// null-routing traffic.
|
|
|
|
ValidateClusters: response.MakeBoolValue(true),
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, vh := range psRoute.GetVirtualHosts() {
|
|
|
|
envoyRouteConfig.VirtualHosts = append(envoyRouteConfig.VirtualHosts, pr.makeEnvoyVHFromProxystateVH(vh))
|
|
|
|
}
|
|
|
|
|
|
|
|
return envoyRouteConfig
|
|
|
|
}
|
|
|
|
|
|
|
|
func (pr *ProxyResources) makeEnvoyVHFromProxystateVH(psVirtualHost *pbproxystate.VirtualHost) *envoy_route_v3.VirtualHost {
|
|
|
|
envoyVirtualHost := &envoy_route_v3.VirtualHost{
|
|
|
|
Name: psVirtualHost.Name,
|
|
|
|
Domains: psVirtualHost.GetDomains(),
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, rr := range psVirtualHost.GetRouteRules() {
|
|
|
|
envoyVirtualHost.Routes = append(envoyVirtualHost.Routes, pr.makeEnvoyRouteFromProxystateRouteRule(rr))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, hm := range psVirtualHost.GetHeaderMutations() {
|
|
|
|
injectEnvoyVirtualHostWithProxystateHeaderMutation(envoyVirtualHost, hm)
|
|
|
|
}
|
|
|
|
|
|
|
|
return envoyVirtualHost
|
|
|
|
}
|
|
|
|
|
|
|
|
func (pr *ProxyResources) makeEnvoyRouteFromProxystateRouteRule(psRouteRule *pbproxystate.RouteRule) *envoy_route_v3.Route {
|
|
|
|
envoyRouteRule := &envoy_route_v3.Route{
|
|
|
|
Match: makeEnvoyRouteMatchFromProxystateRouteMatch(psRouteRule.GetMatch()),
|
|
|
|
Action: pr.makeEnvoyRouteActionFromProxystateRouteDestination(psRouteRule.GetDestination()),
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, hm := range psRouteRule.GetHeaderMutations() {
|
|
|
|
injectEnvoyRouteRuleWithProxystateHeaderMutation(envoyRouteRule, hm)
|
|
|
|
}
|
|
|
|
|
|
|
|
return envoyRouteRule
|
|
|
|
}
|
|
|
|
|
|
|
|
func makeEnvoyRouteMatchFromProxystateRouteMatch(psRouteMatch *pbproxystate.RouteMatch) *envoy_route_v3.RouteMatch {
|
|
|
|
envoyRouteMatch := &envoy_route_v3.RouteMatch{}
|
|
|
|
|
|
|
|
switch psRouteMatch.PathMatch.GetPathMatch().(type) {
|
|
|
|
case *pbproxystate.PathMatch_Exact:
|
|
|
|
envoyRouteMatch.PathSpecifier = &envoy_route_v3.RouteMatch_Path{
|
|
|
|
Path: psRouteMatch.PathMatch.GetExact(),
|
|
|
|
}
|
|
|
|
case *pbproxystate.PathMatch_Prefix:
|
|
|
|
envoyRouteMatch.PathSpecifier = &envoy_route_v3.RouteMatch_Prefix{
|
|
|
|
Prefix: psRouteMatch.PathMatch.GetPrefix(),
|
|
|
|
}
|
|
|
|
case *pbproxystate.PathMatch_Regex:
|
|
|
|
envoyRouteMatch.PathSpecifier = &envoy_route_v3.RouteMatch_SafeRegex{
|
|
|
|
SafeRegex: makeEnvoyRegexMatch(psRouteMatch.PathMatch.GetRegex()),
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
// This shouldn't be possible considering the types of PathMatch
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(psRouteMatch.GetHeaderMatches()) > 0 {
|
|
|
|
envoyRouteMatch.Headers = make([]*envoy_route_v3.HeaderMatcher, 0, len(psRouteMatch.GetHeaderMatches()))
|
|
|
|
}
|
|
|
|
for _, psHM := range psRouteMatch.GetHeaderMatches() {
|
|
|
|
envoyRouteMatch.Headers = append(envoyRouteMatch.Headers, makeEnvoyHeaderMatcherFromProxystateHeaderMatch(psHM))
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(psRouteMatch.MethodMatches) > 0 {
|
|
|
|
methodHeaderRegex := strings.Join(psRouteMatch.MethodMatches, "|")
|
|
|
|
|
|
|
|
eh := &envoy_route_v3.HeaderMatcher{
|
|
|
|
Name: ":method",
|
|
|
|
HeaderMatchSpecifier: &envoy_route_v3.HeaderMatcher_SafeRegexMatch{
|
|
|
|
SafeRegexMatch: makeEnvoyRegexMatch(methodHeaderRegex),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
envoyRouteMatch.Headers = append(envoyRouteMatch.Headers, eh)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(psRouteMatch.GetQueryParameterMatches()) > 0 {
|
|
|
|
envoyRouteMatch.QueryParameters = make([]*envoy_route_v3.QueryParameterMatcher, 0, len(psRouteMatch.GetQueryParameterMatches()))
|
|
|
|
}
|
|
|
|
for _, psQM := range psRouteMatch.GetQueryParameterMatches() {
|
|
|
|
envoyRouteMatch.QueryParameters = append(envoyRouteMatch.QueryParameters, makeEnvoyQueryParamFromProxystateQueryMatch(psQM))
|
|
|
|
}
|
|
|
|
|
|
|
|
return envoyRouteMatch
|
|
|
|
}
|
|
|
|
|
|
|
|
func makeEnvoyRegexMatch(pattern string) *envoy_matcher_v3.RegexMatcher {
|
|
|
|
return &envoy_matcher_v3.RegexMatcher{
|
|
|
|
EngineType: &envoy_matcher_v3.RegexMatcher_GoogleRe2{
|
|
|
|
GoogleRe2: &envoy_matcher_v3.RegexMatcher_GoogleRE2{},
|
|
|
|
},
|
|
|
|
Regex: pattern,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func makeEnvoyHeaderMatcherFromProxystateHeaderMatch(psMatch *pbproxystate.HeaderMatch) *envoy_route_v3.HeaderMatcher {
|
|
|
|
envoyHeaderMatcher := &envoy_route_v3.HeaderMatcher{
|
|
|
|
Name: psMatch.Name,
|
|
|
|
}
|
|
|
|
|
|
|
|
switch psMatch.Match.(type) {
|
|
|
|
case *pbproxystate.HeaderMatch_Exact:
|
2023-09-07 19:03:09 +00:00
|
|
|
envoyHeaderMatcher.HeaderMatchSpecifier = &envoy_route_v3.HeaderMatcher_StringMatch{
|
|
|
|
StringMatch: &envoy_matcher_v3.StringMatcher{
|
|
|
|
MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{
|
|
|
|
Exact: psMatch.GetExact(),
|
|
|
|
},
|
|
|
|
IgnoreCase: false,
|
|
|
|
},
|
2023-08-17 21:04:53 +00:00
|
|
|
}
|
2023-09-07 19:03:09 +00:00
|
|
|
|
2023-08-17 21:04:53 +00:00
|
|
|
case *pbproxystate.HeaderMatch_Regex:
|
2023-09-07 19:03:09 +00:00
|
|
|
envoyHeaderMatcher.HeaderMatchSpecifier = &envoy_route_v3.HeaderMatcher_StringMatch{
|
|
|
|
StringMatch: &envoy_matcher_v3.StringMatcher{
|
|
|
|
MatchPattern: &envoy_matcher_v3.StringMatcher_SafeRegex{
|
|
|
|
SafeRegex: response.MakeEnvoyRegexMatch(psMatch.GetRegex()),
|
|
|
|
},
|
|
|
|
IgnoreCase: false,
|
|
|
|
},
|
2023-08-17 21:04:53 +00:00
|
|
|
}
|
2023-09-07 19:03:09 +00:00
|
|
|
|
2023-08-17 21:04:53 +00:00
|
|
|
case *pbproxystate.HeaderMatch_Prefix:
|
2023-09-07 19:03:09 +00:00
|
|
|
envoyHeaderMatcher.HeaderMatchSpecifier = &envoy_route_v3.HeaderMatcher_StringMatch{
|
|
|
|
StringMatch: &envoy_matcher_v3.StringMatcher{
|
|
|
|
MatchPattern: &envoy_matcher_v3.StringMatcher_Prefix{
|
|
|
|
Prefix: psMatch.GetPrefix(),
|
|
|
|
},
|
|
|
|
IgnoreCase: false,
|
|
|
|
},
|
2023-08-17 21:04:53 +00:00
|
|
|
}
|
|
|
|
case *pbproxystate.HeaderMatch_Suffix:
|
2023-09-07 19:03:09 +00:00
|
|
|
envoyHeaderMatcher.HeaderMatchSpecifier = &envoy_route_v3.HeaderMatcher_StringMatch{
|
|
|
|
StringMatch: &envoy_matcher_v3.StringMatcher{
|
|
|
|
MatchPattern: &envoy_matcher_v3.StringMatcher_Suffix{
|
|
|
|
Suffix: psMatch.GetSuffix(),
|
|
|
|
},
|
|
|
|
IgnoreCase: false,
|
|
|
|
},
|
2023-08-17 21:04:53 +00:00
|
|
|
}
|
2023-09-07 19:03:09 +00:00
|
|
|
|
2023-08-17 21:04:53 +00:00
|
|
|
case *pbproxystate.HeaderMatch_Present:
|
|
|
|
envoyHeaderMatcher.HeaderMatchSpecifier = &envoy_route_v3.HeaderMatcher_PresentMatch{
|
|
|
|
PresentMatch: true,
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
// This shouldn't be possible considering the types of HeaderMatch
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if psMatch.GetInvertMatch() {
|
|
|
|
envoyHeaderMatcher.InvertMatch = true
|
|
|
|
}
|
|
|
|
|
|
|
|
return envoyHeaderMatcher
|
|
|
|
}
|
|
|
|
|
|
|
|
func makeEnvoyQueryParamFromProxystateQueryMatch(psMatch *pbproxystate.QueryParameterMatch) *envoy_route_v3.QueryParameterMatcher {
|
|
|
|
envoyQueryParamMatcher := &envoy_route_v3.QueryParameterMatcher{
|
|
|
|
Name: psMatch.Name,
|
|
|
|
}
|
|
|
|
|
|
|
|
switch psMatch.Match.(type) {
|
|
|
|
case *pbproxystate.QueryParameterMatch_Exact:
|
|
|
|
envoyQueryParamMatcher.QueryParameterMatchSpecifier = &envoy_route_v3.QueryParameterMatcher_StringMatch{
|
|
|
|
StringMatch: &envoy_matcher_v3.StringMatcher{
|
|
|
|
MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{
|
|
|
|
Exact: psMatch.GetExact(),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
case *pbproxystate.QueryParameterMatch_Regex:
|
|
|
|
envoyQueryParamMatcher.QueryParameterMatchSpecifier = &envoy_route_v3.QueryParameterMatcher_StringMatch{
|
|
|
|
StringMatch: &envoy_matcher_v3.StringMatcher{
|
|
|
|
MatchPattern: &envoy_matcher_v3.StringMatcher_SafeRegex{
|
|
|
|
SafeRegex: makeEnvoyRegexMatch(psMatch.GetRegex()),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
case *pbproxystate.QueryParameterMatch_Present:
|
|
|
|
envoyQueryParamMatcher.QueryParameterMatchSpecifier = &envoy_route_v3.QueryParameterMatcher_PresentMatch{
|
|
|
|
PresentMatch: true,
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
// This shouldn't be possible considering the types of QueryMatch
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return envoyQueryParamMatcher
|
|
|
|
}
|
|
|
|
|
2023-11-07 15:00:08 +00:00
|
|
|
func (pr *ProxyResources) addEnvoyClustersAndEndpointsToEnvoyResources(clusterName string) {
|
2023-11-08 22:18:51 +00:00
|
|
|
clusters, endpoints, _ := pr.makeClustersAndEndpoints(clusterName)
|
|
|
|
|
2023-11-07 15:00:08 +00:00
|
|
|
for name, cluster := range clusters {
|
|
|
|
pr.envoyResources[xdscommon.ClusterType][name] = cluster
|
2023-11-08 22:18:51 +00:00
|
|
|
}
|
2023-11-07 15:00:08 +00:00
|
|
|
|
2023-11-08 22:18:51 +00:00
|
|
|
for name, ep := range endpoints {
|
|
|
|
pr.envoyResources[xdscommon.EndpointType][name] = ep
|
2023-11-07 15:00:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-17 21:04:53 +00:00
|
|
|
// TODO (dans): Will this always be envoy_route_v3.Route_Route?
|
|
|
|
// Definitely for connect proxies this is the only option.
|
|
|
|
func (pr *ProxyResources) makeEnvoyRouteActionFromProxystateRouteDestination(psRouteDestination *pbproxystate.RouteDestination) *envoy_route_v3.Route_Route {
|
|
|
|
envoyRouteRoute := &envoy_route_v3.Route_Route{
|
|
|
|
Route: &envoy_route_v3.RouteAction{},
|
|
|
|
}
|
|
|
|
|
|
|
|
switch psRouteDestination.Destination.(type) {
|
|
|
|
case *pbproxystate.RouteDestination_Cluster:
|
|
|
|
psCluster := psRouteDestination.GetCluster()
|
|
|
|
envoyRouteRoute.Route.ClusterSpecifier = &envoy_route_v3.RouteAction_Cluster{
|
|
|
|
Cluster: psCluster.GetName(),
|
|
|
|
}
|
2023-11-07 15:00:08 +00:00
|
|
|
pr.addEnvoyClustersAndEndpointsToEnvoyResources(psCluster.Name)
|
2023-08-17 21:04:53 +00:00
|
|
|
|
|
|
|
case *pbproxystate.RouteDestination_WeightedClusters:
|
|
|
|
psWeightedClusters := psRouteDestination.GetWeightedClusters()
|
|
|
|
envoyClusters := make([]*envoy_route_v3.WeightedCluster_ClusterWeight, 0, len(psWeightedClusters.GetClusters()))
|
|
|
|
totalWeight := 0
|
|
|
|
for _, psCluster := range psWeightedClusters.GetClusters() {
|
2023-11-07 15:00:08 +00:00
|
|
|
pr.addEnvoyClustersAndEndpointsToEnvoyResources(psCluster.Name)
|
|
|
|
|
2023-08-17 21:04:53 +00:00
|
|
|
totalWeight += int(psCluster.Weight.GetValue())
|
|
|
|
envoyClusters = append(envoyClusters, makeEnvoyClusterWeightFromProxystateWeightedCluster(psCluster))
|
|
|
|
}
|
|
|
|
var envoyWeightScale *wrapperspb.UInt32Value
|
|
|
|
if totalWeight == 10000 {
|
|
|
|
envoyWeightScale = response.MakeUint32Value(10000)
|
|
|
|
}
|
|
|
|
|
|
|
|
envoyRouteRoute.Route.ClusterSpecifier = &envoy_route_v3.RouteAction_WeightedClusters{
|
|
|
|
WeightedClusters: &envoy_route_v3.WeightedCluster{
|
|
|
|
Clusters: envoyClusters,
|
|
|
|
TotalWeight: envoyWeightScale,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
// This shouldn't be possible considering the types of Destination
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
injectEnvoyRouteActionWithProxystateDestinationConfig(envoyRouteRoute.Route, psRouteDestination.GetDestinationConfiguration())
|
|
|
|
|
|
|
|
if psRouteDestination.GetDestinationConfiguration() != nil {
|
|
|
|
config := psRouteDestination.GetDestinationConfiguration()
|
|
|
|
action := envoyRouteRoute.Route
|
|
|
|
|
|
|
|
action.PrefixRewrite = config.GetPrefixRewrite()
|
|
|
|
|
|
|
|
if config.GetTimeoutConfig().GetTimeout() != nil {
|
|
|
|
action.Timeout = config.GetTimeoutConfig().GetTimeout()
|
|
|
|
}
|
|
|
|
|
|
|
|
if config.GetTimeoutConfig().GetTimeout() != nil {
|
|
|
|
action.Timeout = config.GetTimeoutConfig().GetTimeout()
|
|
|
|
}
|
|
|
|
|
|
|
|
if config.GetTimeoutConfig().GetIdleTimeout() != nil {
|
|
|
|
action.IdleTimeout = config.GetTimeoutConfig().GetIdleTimeout()
|
|
|
|
}
|
|
|
|
|
|
|
|
if config.GetRetryPolicy() != nil {
|
|
|
|
action.RetryPolicy = makeEnvoyRetryPolicyFromProxystateRetryPolicy(config.GetRetryPolicy())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return envoyRouteRoute
|
|
|
|
}
|
|
|
|
|
|
|
|
func makeEnvoyClusterWeightFromProxystateWeightedCluster(cluster *pbproxystate.L7WeightedDestinationCluster) *envoy_route_v3.WeightedCluster_ClusterWeight {
|
2023-11-07 15:00:08 +00:00
|
|
|
envoyClusterWeight := makeEnvoyClusterWeightFromNameAndWeight(cluster.GetName(), cluster.GetWeight())
|
2023-08-17 21:04:53 +00:00
|
|
|
|
|
|
|
for _, hm := range cluster.GetHeaderMutations() {
|
|
|
|
injectEnvoyClusterWeightWithProxystateHeaderMutation(envoyClusterWeight, hm)
|
|
|
|
}
|
|
|
|
|
|
|
|
return envoyClusterWeight
|
|
|
|
}
|
|
|
|
|
2023-11-07 15:00:08 +00:00
|
|
|
func makeEnvoyClusterWeightFromNameAndWeight(name string, weight *wrapperspb.UInt32Value) *envoy_route_v3.WeightedCluster_ClusterWeight {
|
|
|
|
envoyClusterWeight := &envoy_route_v3.WeightedCluster_ClusterWeight{
|
|
|
|
Name: name,
|
|
|
|
Weight: weight,
|
|
|
|
}
|
|
|
|
|
|
|
|
return envoyClusterWeight
|
|
|
|
}
|
|
|
|
|
2023-08-17 21:04:53 +00:00
|
|
|
func injectEnvoyClusterWeightWithProxystateHeaderMutation(envoyClusterWeight *envoy_route_v3.WeightedCluster_ClusterWeight, mutation *pbproxystate.HeaderMutation) {
|
|
|
|
mutation.GetAction()
|
|
|
|
switch mutation.GetAction().(type) {
|
|
|
|
case *pbproxystate.HeaderMutation_RequestHeaderAdd:
|
|
|
|
action := mutation.GetRequestHeaderAdd()
|
|
|
|
header := action.GetHeader()
|
|
|
|
app := action.GetAppendAction() == pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD
|
|
|
|
|
|
|
|
hvo := &envoy_core_v3.HeaderValueOption{
|
|
|
|
Header: &envoy_core_v3.HeaderValue{
|
|
|
|
Key: header.GetKey(),
|
|
|
|
Value: header.GetValue(),
|
|
|
|
},
|
|
|
|
Append: response.MakeBoolValue(app),
|
|
|
|
}
|
|
|
|
envoyClusterWeight.RequestHeadersToAdd = append(envoyClusterWeight.RequestHeadersToAdd, hvo)
|
|
|
|
|
|
|
|
case *pbproxystate.HeaderMutation_RequestHeaderRemove:
|
|
|
|
action := mutation.GetRequestHeaderRemove()
|
|
|
|
envoyClusterWeight.RequestHeadersToRemove = append(envoyClusterWeight.RequestHeadersToRemove, action.GetHeaderKeys()...)
|
|
|
|
|
|
|
|
case *pbproxystate.HeaderMutation_ResponseHeaderAdd:
|
|
|
|
action := mutation.GetResponseHeaderAdd()
|
|
|
|
header := action.GetHeader()
|
|
|
|
app := action.GetAppendAction() == pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD
|
|
|
|
|
|
|
|
hvo := &envoy_core_v3.HeaderValueOption{
|
|
|
|
Header: &envoy_core_v3.HeaderValue{
|
|
|
|
Key: header.GetKey(),
|
|
|
|
Value: header.GetValue(),
|
|
|
|
},
|
|
|
|
Append: response.MakeBoolValue(app),
|
|
|
|
}
|
|
|
|
envoyClusterWeight.ResponseHeadersToAdd = append(envoyClusterWeight.ResponseHeadersToAdd, hvo)
|
|
|
|
|
|
|
|
case *pbproxystate.HeaderMutation_ResponseHeaderRemove:
|
|
|
|
action := mutation.GetResponseHeaderRemove()
|
|
|
|
envoyClusterWeight.ResponseHeadersToRemove = append(envoyClusterWeight.ResponseHeadersToRemove, action.GetHeaderKeys()...)
|
|
|
|
|
|
|
|
default:
|
|
|
|
// This shouldn't be possible considering the types of Destination
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func injectEnvoyRouteActionWithProxystateDestinationConfig(envoyAction *envoy_route_v3.RouteAction, config *pbproxystate.DestinationConfiguration) {
|
|
|
|
if config == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(config.GetHashPolicies()) > 0 {
|
|
|
|
envoyAction.HashPolicy = make([]*envoy_route_v3.RouteAction_HashPolicy, 0, len(config.GetHashPolicies()))
|
|
|
|
}
|
|
|
|
for _, policy := range config.GetHashPolicies() {
|
|
|
|
envoyPolicy := makeEnvoyHashPolicyFromProxystateLBHashPolicy(policy)
|
|
|
|
envoyAction.HashPolicy = append(envoyAction.HashPolicy, envoyPolicy)
|
|
|
|
}
|
|
|
|
|
|
|
|
if config.AutoHostRewrite != nil {
|
|
|
|
envoyAction.HostRewriteSpecifier = &envoy_route_v3.RouteAction_AutoHostRewrite{
|
|
|
|
AutoHostRewrite: config.AutoHostRewrite,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func makeEnvoyHashPolicyFromProxystateLBHashPolicy(psPolicy *pbproxystate.LoadBalancerHashPolicy) *envoy_route_v3.RouteAction_HashPolicy {
|
|
|
|
switch psPolicy.GetPolicy().(type) {
|
|
|
|
case *pbproxystate.LoadBalancerHashPolicy_ConnectionProperties:
|
|
|
|
return &envoy_route_v3.RouteAction_HashPolicy{
|
|
|
|
PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_ConnectionProperties_{
|
|
|
|
ConnectionProperties: &envoy_route_v3.RouteAction_HashPolicy_ConnectionProperties{
|
|
|
|
SourceIp: true, // always true
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Terminal: psPolicy.GetConnectionProperties().GetTerminal(),
|
|
|
|
}
|
|
|
|
|
|
|
|
case *pbproxystate.LoadBalancerHashPolicy_Header:
|
|
|
|
return &envoy_route_v3.RouteAction_HashPolicy{
|
|
|
|
PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_Header_{
|
|
|
|
Header: &envoy_route_v3.RouteAction_HashPolicy_Header{
|
|
|
|
HeaderName: psPolicy.GetHeader().GetName(),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Terminal: psPolicy.GetHeader().GetTerminal(),
|
|
|
|
}
|
|
|
|
|
|
|
|
case *pbproxystate.LoadBalancerHashPolicy_Cookie:
|
|
|
|
cookie := &envoy_route_v3.RouteAction_HashPolicy_Cookie{
|
|
|
|
Name: psPolicy.GetCookie().GetName(),
|
|
|
|
Path: psPolicy.GetCookie().GetPath(),
|
|
|
|
Ttl: psPolicy.GetCookie().GetTtl(),
|
|
|
|
}
|
|
|
|
|
|
|
|
return &envoy_route_v3.RouteAction_HashPolicy{
|
|
|
|
PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_Cookie_{
|
|
|
|
Cookie: cookie,
|
|
|
|
},
|
|
|
|
Terminal: psPolicy.GetCookie().GetTerminal(),
|
|
|
|
}
|
|
|
|
|
|
|
|
case *pbproxystate.LoadBalancerHashPolicy_QueryParameter:
|
|
|
|
return &envoy_route_v3.RouteAction_HashPolicy{
|
|
|
|
PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_QueryParameter_{
|
|
|
|
QueryParameter: &envoy_route_v3.RouteAction_HashPolicy_QueryParameter{
|
|
|
|
Name: psPolicy.GetQueryParameter().GetName(),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Terminal: psPolicy.GetQueryParameter().GetTerminal(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// This shouldn't be possible considering the types of LoadBalancerPolicy
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func makeEnvoyRetryPolicyFromProxystateRetryPolicy(psRetryPolicy *pbproxystate.RetryPolicy) *envoy_route_v3.RetryPolicy {
|
|
|
|
return &envoy_route_v3.RetryPolicy{
|
|
|
|
NumRetries: psRetryPolicy.GetNumRetries(),
|
|
|
|
RetriableStatusCodes: psRetryPolicy.GetRetriableStatusCodes(),
|
|
|
|
RetryOn: psRetryPolicy.GetRetryOn(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func injectEnvoyRouteRuleWithProxystateHeaderMutation(envoyRouteRule *envoy_route_v3.Route, mutation *pbproxystate.HeaderMutation) {
|
|
|
|
mutation.GetAction()
|
|
|
|
switch mutation.GetAction().(type) {
|
|
|
|
case *pbproxystate.HeaderMutation_RequestHeaderAdd:
|
|
|
|
action := mutation.GetRequestHeaderAdd()
|
|
|
|
header := action.GetHeader()
|
|
|
|
app := action.GetAppendAction() == pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD
|
|
|
|
|
|
|
|
hvo := &envoy_core_v3.HeaderValueOption{
|
|
|
|
Header: &envoy_core_v3.HeaderValue{
|
|
|
|
Key: header.GetKey(),
|
|
|
|
Value: header.GetValue(),
|
|
|
|
},
|
|
|
|
Append: response.MakeBoolValue(app),
|
|
|
|
}
|
|
|
|
envoyRouteRule.RequestHeadersToAdd = append(envoyRouteRule.RequestHeadersToAdd, hvo)
|
|
|
|
|
|
|
|
case *pbproxystate.HeaderMutation_RequestHeaderRemove:
|
|
|
|
action := mutation.GetRequestHeaderRemove()
|
|
|
|
envoyRouteRule.RequestHeadersToRemove = append(envoyRouteRule.RequestHeadersToRemove, action.GetHeaderKeys()...)
|
|
|
|
|
|
|
|
case *pbproxystate.HeaderMutation_ResponseHeaderAdd:
|
|
|
|
action := mutation.GetResponseHeaderAdd()
|
|
|
|
header := action.GetHeader()
|
|
|
|
app := action.GetAppendAction() == pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD
|
|
|
|
|
|
|
|
hvo := &envoy_core_v3.HeaderValueOption{
|
|
|
|
Header: &envoy_core_v3.HeaderValue{
|
|
|
|
Key: header.GetKey(),
|
|
|
|
Value: header.GetValue(),
|
|
|
|
},
|
|
|
|
Append: response.MakeBoolValue(app),
|
|
|
|
}
|
|
|
|
envoyRouteRule.ResponseHeadersToAdd = append(envoyRouteRule.ResponseHeadersToAdd, hvo)
|
|
|
|
|
|
|
|
case *pbproxystate.HeaderMutation_ResponseHeaderRemove:
|
|
|
|
action := mutation.GetResponseHeaderRemove()
|
|
|
|
envoyRouteRule.ResponseHeadersToRemove = append(envoyRouteRule.ResponseHeadersToRemove, action.GetHeaderKeys()...)
|
|
|
|
|
|
|
|
default:
|
|
|
|
// This shouldn't be possible considering the types of Destination
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func injectEnvoyVirtualHostWithProxystateHeaderMutation(envoyVirtualHost *envoy_route_v3.VirtualHost, mutation *pbproxystate.HeaderMutation) {
|
|
|
|
mutation.GetAction()
|
|
|
|
switch mutation.GetAction().(type) {
|
|
|
|
case *pbproxystate.HeaderMutation_RequestHeaderAdd:
|
|
|
|
action := mutation.GetRequestHeaderAdd()
|
|
|
|
header := action.GetHeader()
|
|
|
|
app := action.GetAppendAction() == pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD
|
|
|
|
|
|
|
|
hvo := &envoy_core_v3.HeaderValueOption{
|
|
|
|
Header: &envoy_core_v3.HeaderValue{
|
|
|
|
Key: header.GetKey(),
|
|
|
|
Value: header.GetValue(),
|
|
|
|
},
|
|
|
|
Append: response.MakeBoolValue(app),
|
|
|
|
}
|
|
|
|
envoyVirtualHost.RequestHeadersToAdd = append(envoyVirtualHost.RequestHeadersToAdd, hvo)
|
|
|
|
|
|
|
|
case *pbproxystate.HeaderMutation_RequestHeaderRemove:
|
|
|
|
action := mutation.GetRequestHeaderRemove()
|
|
|
|
envoyVirtualHost.RequestHeadersToRemove = append(envoyVirtualHost.RequestHeadersToRemove, action.GetHeaderKeys()...)
|
|
|
|
|
|
|
|
case *pbproxystate.HeaderMutation_ResponseHeaderAdd:
|
|
|
|
action := mutation.GetResponseHeaderAdd()
|
|
|
|
header := action.GetHeader()
|
|
|
|
app := action.GetAppendAction() == pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD
|
|
|
|
|
|
|
|
hvo := &envoy_core_v3.HeaderValueOption{
|
|
|
|
Header: &envoy_core_v3.HeaderValue{
|
|
|
|
Key: header.GetKey(),
|
|
|
|
Value: header.GetValue(),
|
|
|
|
},
|
|
|
|
Append: response.MakeBoolValue(app),
|
|
|
|
}
|
|
|
|
envoyVirtualHost.ResponseHeadersToAdd = append(envoyVirtualHost.ResponseHeadersToAdd, hvo)
|
|
|
|
|
|
|
|
case *pbproxystate.HeaderMutation_ResponseHeaderRemove:
|
|
|
|
action := mutation.GetResponseHeaderRemove()
|
|
|
|
envoyVirtualHost.ResponseHeadersToRemove = append(envoyVirtualHost.ResponseHeadersToRemove, action.GetHeaderKeys()...)
|
|
|
|
|
|
|
|
default:
|
|
|
|
// This shouldn't be possible considering the types of Destination
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|