Skip to content

Commit

Permalink
Translate response header modifier(s) from HTTPRoute onto Consul conf…
Browse files Browse the repository at this point in the history
…ig entry
  • Loading branch information
nathancoleman committed Sep 5, 2023
1 parent c6b703d commit 1ea3771
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 37 deletions.
67 changes: 49 additions & 18 deletions control-plane/api-gateway/common/translation.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,12 +178,13 @@ func (t ResourceTranslator) translateHTTPRouteRule(route gwv1beta1.HTTPRoute, ru
}

matches := ConvertSliceFunc(rule.Matches, t.translateHTTPMatch)
filters := t.translateHTTPFilters(rule.Filters, resources, route.Namespace)
filters, responseFilters := t.translateHTTPFilters(rule.Filters, resources, route.Namespace)

return api.HTTPRouteRule{
Services: services,
Matches: matches,
Filters: filters,
Filters: filters,
Matches: matches,
ResponseFilters: responseFilters,
Services: services,
}, true
}

Expand All @@ -196,28 +197,30 @@ func (t ResourceTranslator) translateHTTPBackendRef(route gwv1beta1.HTTPRoute, r
isServiceRef := NilOrEqual(ref.Group, "") && NilOrEqual(ref.Kind, "Service")

if isServiceRef && resources.HasService(id) && resources.HTTPRouteCanReferenceBackend(route, ref.BackendRef) {
filters := t.translateHTTPFilters(ref.Filters, resources, route.Namespace)
filters, responseFilters := t.translateHTTPFilters(ref.Filters, resources, route.Namespace)
service := resources.Service(id)
return api.HTTPService{
Name: service.Name,
Namespace: service.Namespace,
Partition: t.ConsulPartition,
Filters: filters,
Weight: DerefIntOr(ref.Weight, 1),
Name: service.Name,
Namespace: service.Namespace,
Partition: t.ConsulPartition,
Filters: filters,
ResponseFilters: responseFilters,
Weight: DerefIntOr(ref.Weight, 1),
}, true
}

isMeshServiceRef := DerefEqual(ref.Group, v1alpha1.ConsulHashicorpGroup) && DerefEqual(ref.Kind, v1alpha1.MeshServiceKind)
if isMeshServiceRef && resources.HasMeshService(id) && resources.HTTPRouteCanReferenceBackend(route, ref.BackendRef) {
filters := t.translateHTTPFilters(ref.Filters, resources, route.Namespace)
filters, responseFilters := t.translateHTTPFilters(ref.Filters, resources, route.Namespace)
service := resources.MeshService(id)

return api.HTTPService{
Name: service.Name,
Namespace: service.Namespace,
Partition: t.ConsulPartition,
Filters: filters,
Weight: DerefIntOr(ref.Weight, 1),
Name: service.Name,
Namespace: service.Namespace,
Partition: t.ConsulPartition,
Filters: filters,
ResponseFilters: responseFilters,
Weight: DerefIntOr(ref.Weight, 1),
}, true
}

Expand Down Expand Up @@ -275,15 +278,24 @@ func (t ResourceTranslator) translateHTTPQueryMatch(match gwv1beta1.HTTPQueryPar
}
}

func (t ResourceTranslator) translateHTTPFilters(filters []gwv1beta1.HTTPRouteFilter, resourceMap *ResourceMap, namespace string) api.HTTPFilters {
func (t ResourceTranslator) translateHTTPFilters(filters []gwv1beta1.HTTPRouteFilter, resourceMap *ResourceMap, namespace string) (api.HTTPFilters, api.HTTPResponseFilters) {
var urlRewrite *api.URLRewrite
// TODO Consider only setting a filter on the resulting Consul config entry
// if we encounter a gwb1beta1.HTTPRouteFilter that requires it
consulFilter := api.HTTPHeaderFilter{
Add: make(map[string]string),
Set: make(map[string]string),
}
consulResponseFilter := api.HTTPHeaderFilter{
Add: make(map[string]string),
Set: make(map[string]string),
}
var retryFilter *api.RetryFilter
var timeoutFilter *api.TimeoutFilter

// Convert Gateway API filters to portions of the Consul request and response filters.
// Multiple filters applying the same or conflicting operations are allowed but may
// result in unexpected behavior.
for _, filter := range filters {
if filter.RequestHeaderModifier != nil {
consulFilter.Remove = append(consulFilter.Remove, filter.RequestHeaderModifier.Remove...)
Expand All @@ -297,6 +309,18 @@ func (t ResourceTranslator) translateHTTPFilters(filters []gwv1beta1.HTTPRouteFi
}
}

if filter.ResponseHeaderModifier != nil {
consulResponseFilter.Remove = append(consulResponseFilter.Remove, filter.ResponseHeaderModifier.Remove...)

for _, toAdd := range filter.ResponseHeaderModifier.Add {
consulResponseFilter.Add[string(toAdd.Name)] = toAdd.Value
}

for _, toSet := range filter.ResponseHeaderModifier.Set {
consulResponseFilter.Set[string(toSet.Name)] = toSet.Value
}
}

// we drop any path rewrites that are not prefix matches as we don't support those
if filter.URLRewrite != nil &&
filter.URLRewrite.Path != nil &&
Expand Down Expand Up @@ -338,12 +362,19 @@ func (t ResourceTranslator) translateHTTPFilters(filters []gwv1beta1.HTTPRouteFi
}

}
return api.HTTPFilters{

requestFilter := api.HTTPFilters{
Headers: []api.HTTPHeaderFilter{consulFilter},
URLRewrite: urlRewrite,
RetryFilter: retryFilter,
TimeoutFilter: timeoutFilter,
}

responseFilter := api.HTTPResponseFilters{
Headers: []api.HTTPHeaderFilter{consulResponseFilter},
}

return requestFilter, responseFilter
}

func (t ResourceTranslator) ToTCPRoute(route gwv1alpha2.TCPRoute, resources *ResourceMap) *api.TCPRouteConfigEntry {
Expand Down
84 changes: 66 additions & 18 deletions control-plane/api-gateway/common/translation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,9 @@ func TestTranslator_ToHTTPRoute(t *testing.T) {
},
URLRewrite: &api.URLRewrite{Path: "v1"},
},
ResponseFilters: api.HTTPResponseFilters{
Headers: []api.HTTPHeaderFilter{{Add: map[string]string{}, Set: map[string]string{}}},
},
Matches: []api.HTTPMatch{
{
Headers: []api.HTTPHeaderMatch{
Expand All @@ -536,8 +539,8 @@ func TestTranslator_ToHTTPRoute(t *testing.T) {
},
Services: []api.HTTPService{
{
Name: "service one",
Weight: 45,
Name: "service one",
Namespace: "other",
Filters: api.HTTPFilters{
Headers: []api.HTTPHeaderFilter{
{
Expand All @@ -555,7 +558,10 @@ func TestTranslator_ToHTTPRoute(t *testing.T) {
Path: "path",
},
},
Namespace: "other",
ResponseFilters: api.HTTPResponseFilters{
Headers: []api.HTTPHeaderFilter{{Add: map[string]string{}, Set: map[string]string{}}},
},
Weight: 45,
},
},
},
Expand Down Expand Up @@ -715,6 +721,9 @@ func TestTranslator_ToHTTPRoute(t *testing.T) {
},
},
},
ResponseFilters: api.HTTPResponseFilters{
Headers: []api.HTTPHeaderFilter{{Add: map[string]string{}, Set: map[string]string{}}},
},
Matches: []api.HTTPMatch{
{
Headers: []api.HTTPHeaderMatch{
Expand All @@ -740,8 +749,8 @@ func TestTranslator_ToHTTPRoute(t *testing.T) {
},
Services: []api.HTTPService{
{
Name: "service one",
Weight: 45,
Name: "service one",
Namespace: "some ns",
Filters: api.HTTPFilters{
Headers: []api.HTTPHeaderFilter{
{
Expand All @@ -759,7 +768,10 @@ func TestTranslator_ToHTTPRoute(t *testing.T) {
Path: "path",
},
},
Namespace: "some ns",
ResponseFilters: api.HTTPResponseFilters{
Headers: []api.HTTPHeaderFilter{{Add: map[string]string{}, Set: map[string]string{}}},
},
Weight: 45,
},
},
},
Expand Down Expand Up @@ -927,6 +939,9 @@ func TestTranslator_ToHTTPRoute(t *testing.T) {
},
URLRewrite: &api.URLRewrite{Path: "v1"},
},
ResponseFilters: api.HTTPResponseFilters{
Headers: []api.HTTPHeaderFilter{{Add: map[string]string{}, Set: map[string]string{}}},
},
Matches: []api.HTTPMatch{
{
Headers: []api.HTTPHeaderMatch{
Expand All @@ -952,8 +967,8 @@ func TestTranslator_ToHTTPRoute(t *testing.T) {
},
Services: []api.HTTPService{
{
Name: "service one",
Weight: 45,
Name: "service one",
Namespace: "some ns",
Filters: api.HTTPFilters{
Headers: []api.HTTPHeaderFilter{
{
Expand All @@ -971,7 +986,10 @@ func TestTranslator_ToHTTPRoute(t *testing.T) {
Path: "path",
},
},
Namespace: "some ns",
ResponseFilters: api.HTTPResponseFilters{
Headers: []api.HTTPHeaderFilter{{Add: map[string]string{}, Set: map[string]string{}}},
},
Weight: 45,
},
},
},
Expand Down Expand Up @@ -1153,6 +1171,9 @@ func TestTranslator_ToHTTPRoute(t *testing.T) {
},
URLRewrite: &api.URLRewrite{Path: "v1"},
},
ResponseFilters: api.HTTPResponseFilters{
Headers: []api.HTTPHeaderFilter{{Add: map[string]string{}, Set: map[string]string{}}},
},
Matches: []api.HTTPMatch{
{
Headers: []api.HTTPHeaderMatch{
Expand All @@ -1177,10 +1198,17 @@ func TestTranslator_ToHTTPRoute(t *testing.T) {
},
},
Services: []api.HTTPService{
{Name: "some-override", Namespace: "svc-ns", Weight: 1, Filters: api.HTTPFilters{Headers: []api.HTTPHeaderFilter{{Add: make(map[string]string), Set: make(map[string]string)}}}},
{
Name: "service one",
Weight: 45,
Name: "some-override",
Namespace: "svc-ns",
Weight: 1,
Filters: api.HTTPFilters{Headers: []api.HTTPHeaderFilter{{Add: make(map[string]string), Set: make(map[string]string)}}},
ResponseFilters: api.HTTPResponseFilters{
Headers: []api.HTTPHeaderFilter{{Add: map[string]string{}, Set: map[string]string{}}},
}},
{
Name: "service one",
Namespace: "some ns",
Filters: api.HTTPFilters{
Headers: []api.HTTPHeaderFilter{
{
Expand All @@ -1198,7 +1226,10 @@ func TestTranslator_ToHTTPRoute(t *testing.T) {
Path: "path",
},
},
Namespace: "some ns",
ResponseFilters: api.HTTPResponseFilters{
Headers: []api.HTTPHeaderFilter{{Add: map[string]string{}, Set: map[string]string{}}},
},
Weight: 45,
},
},
},
Expand Down Expand Up @@ -1349,6 +1380,9 @@ func TestTranslator_ToHTTPRoute(t *testing.T) {
RetryOnConnectFailure: pointer.Bool(false),
},
},
ResponseFilters: api.HTTPResponseFilters{
Headers: []api.HTTPHeaderFilter{{Add: map[string]string{}, Set: map[string]string{}}},
},
Matches: []api.HTTPMatch{
{
Headers: []api.HTTPHeaderMatch{
Expand Down Expand Up @@ -1385,6 +1419,9 @@ func TestTranslator_ToHTTPRoute(t *testing.T) {
RetryOnConnectFailure: pointer.Bool(false),
},
},
ResponseFilters: api.HTTPResponseFilters{
Headers: []api.HTTPHeaderFilter{{Add: map[string]string{}, Set: map[string]string{}}},
},
Namespace: "other",
},
},
Expand Down Expand Up @@ -1603,10 +1640,11 @@ func TestResourceTranslator_translateHTTPFilters(t1 *testing.T) {
filters []gwv1beta1.HTTPRouteFilter
}
tests := []struct {
name string
fields fields
args args
want api.HTTPFilters
name string
fields fields
args args
want api.HTTPFilters
wantResponseFilters api.HTTPResponseFilters
}{
{
name: "no httproutemodifier set",
Expand All @@ -1627,6 +1665,14 @@ func TestResourceTranslator_translateHTTPFilters(t1 *testing.T) {
},
URLRewrite: nil,
},
wantResponseFilters: api.HTTPResponseFilters{
Headers: []api.HTTPHeaderFilter{
{
Add: map[string]string{},
Set: map[string]string{},
},
},
},
},
}
for _, tt := range tests {
Expand All @@ -1639,7 +1685,9 @@ func TestResourceTranslator_translateHTTPFilters(t1 *testing.T) {
ConsulPartition: tt.fields.ConsulPartition,
Datacenter: tt.fields.Datacenter,
}
assert.Equalf(t1, tt.want, t.translateHTTPFilters(tt.args.filters, nil, ""), "translateHTTPFilters(%v)", tt.args.filters)
requestHeaders, responseHeaders := t.translateHTTPFilters(tt.args.filters, nil, "")
assert.Equalf(t1, tt.want, requestHeaders, "translateHTTPFilters(%v)", tt.args.filters)
assert.Equalf(t1, tt.wantResponseFilters, responseHeaders, "translateHTTPFilters(%v)", tt.args.filters)
})
}
}
2 changes: 1 addition & 1 deletion control-plane/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ require (
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20230825213844-4ea04860c5ed
github.com/hashicorp/consul-server-connection-manager v0.1.4
github.com/hashicorp/consul/api v1.10.1-0.20230825164720-ecdcde430924
github.com/hashicorp/consul/api v1.10.1-0.20230905222646-8560ed52ad25
github.com/hashicorp/consul/proto-public v0.1.2-0.20230829221456-f8812eddf1ef
github.com/hashicorp/consul/sdk v0.14.1
github.com/hashicorp/go-bexpr v0.1.11
Expand Down
4 changes: 4 additions & 0 deletions control-plane/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,10 @@ github.com/hashicorp/consul-server-connection-manager v0.1.4 h1:wrcSRV6WGXFBNpNb
github.com/hashicorp/consul-server-connection-manager v0.1.4/go.mod h1:LMqHkALoLP0HUQKOG21xXYr0YPUayIQIHNTlmxG100E=
github.com/hashicorp/consul/api v1.10.1-0.20230825164720-ecdcde430924 h1:NPhzdwDho2r8pQv31oeGLlco7fnJ1i0WLYjtSXqWEck=
github.com/hashicorp/consul/api v1.10.1-0.20230825164720-ecdcde430924/go.mod h1:NZJGRFYruc/80wYowkPFCp1LbGmJC9L8izrwfyVx/Wg=
github.com/hashicorp/consul/api v1.10.1-0.20230905215137-197bf4dc669c h1:rAZ2oeDSVycD6kaVeOy9x+KenrLfIXmnDMuSVpYKqPs=
github.com/hashicorp/consul/api v1.10.1-0.20230905215137-197bf4dc669c/go.mod h1:NZJGRFYruc/80wYowkPFCp1LbGmJC9L8izrwfyVx/Wg=
github.com/hashicorp/consul/api v1.10.1-0.20230905222646-8560ed52ad25 h1:8OdmroCFwsV05gWNWGIOEfWGkDm0gFDyC0MTAybkwT0=
github.com/hashicorp/consul/api v1.10.1-0.20230905222646-8560ed52ad25/go.mod h1:NZJGRFYruc/80wYowkPFCp1LbGmJC9L8izrwfyVx/Wg=
github.com/hashicorp/consul/proto-public v0.1.2-0.20230829221456-f8812eddf1ef h1:Vt5NSnXc+RslTxXH2pz7dCb3hnE33CD2TrBP5AIQtMg=
github.com/hashicorp/consul/proto-public v0.1.2-0.20230829221456-f8812eddf1ef/go.mod h1:ENwzmloQTUPAYPu7nC1mli3VY0Ny9QNi/FSzJ+KlZD0=
github.com/hashicorp/consul/sdk v0.4.1-0.20230825164720-ecdcde430924 h1:gkb6/ix0Tg1Th5FTjyq4QklLgrtIVQ/TUB0kbhIcPsY=
Expand Down

0 comments on commit 1ea3771

Please sign in to comment.