APIGW: Routes with duplicate parents should be invalid (#16926)
* ensure route parents are unique when creating an http route * Ensure tcp route parents are unique * Added unit tests
This commit is contained in:
parent
91fd8b7917
commit
3d11e9b26a
|
@ -4,6 +4,7 @@
|
|||
package structs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
|
@ -143,10 +144,17 @@ func (e *HTTPRouteConfigEntry) Validate() error {
|
|||
APIGateway: true,
|
||||
}
|
||||
|
||||
uniques := make(map[ResourceReference]struct{}, len(e.Parents))
|
||||
|
||||
for _, parent := range e.Parents {
|
||||
if !validParentKinds[parent.Kind] {
|
||||
return fmt.Errorf("unsupported parent kind: %q, must be 'api-gateway'", parent.Kind)
|
||||
}
|
||||
|
||||
if _, ok := uniques[parent]; ok {
|
||||
return errors.New("route parents must be unique")
|
||||
}
|
||||
uniques[parent] = struct{}{}
|
||||
}
|
||||
|
||||
if err := validateConfigEntryMeta(e.Meta); err != nil {
|
||||
|
@ -534,10 +542,19 @@ func (e *TCPRouteConfigEntry) Validate() error {
|
|||
if len(e.Services) > 1 {
|
||||
return fmt.Errorf("tcp-route currently only supports one service")
|
||||
}
|
||||
|
||||
uniques := make(map[ResourceReference]struct{}, len(e.Parents))
|
||||
|
||||
for _, parent := range e.Parents {
|
||||
if !validParentKinds[parent.Kind] {
|
||||
return fmt.Errorf("unsupported parent kind: %q, must be 'api-gateway'", parent.Kind)
|
||||
}
|
||||
|
||||
if _, ok := uniques[parent]; ok {
|
||||
return errors.New("route parents must be unique")
|
||||
}
|
||||
uniques[parent] = struct{}{}
|
||||
|
||||
}
|
||||
|
||||
if err := validateConfigEntryMeta(e.Meta); err != nil {
|
||||
|
|
|
@ -6,8 +6,9 @@ package structs
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/acl"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/hashicorp/consul/acl"
|
||||
)
|
||||
|
||||
func TestTCPRoute(t *testing.T) {
|
||||
|
@ -60,6 +61,78 @@ func TestTCPRoute(t *testing.T) {
|
|||
},
|
||||
validateErr: "unsupported parent kind",
|
||||
},
|
||||
"duplicate parents with no listener specified": {
|
||||
entry: &TCPRouteConfigEntry{
|
||||
Kind: TCPRoute,
|
||||
Name: "route-two",
|
||||
Parents: []ResourceReference{
|
||||
{
|
||||
Kind: "api-gateway",
|
||||
Name: "gateway",
|
||||
},
|
||||
{
|
||||
Kind: "api-gateway",
|
||||
Name: "gateway",
|
||||
},
|
||||
},
|
||||
},
|
||||
validateErr: "route parents must be unique",
|
||||
},
|
||||
"duplicate parents with listener specified": {
|
||||
entry: &TCPRouteConfigEntry{
|
||||
Kind: TCPRoute,
|
||||
Name: "route-two",
|
||||
Parents: []ResourceReference{
|
||||
{
|
||||
Kind: "api-gateway",
|
||||
Name: "gateway",
|
||||
SectionName: "same",
|
||||
},
|
||||
{
|
||||
Kind: "api-gateway",
|
||||
Name: "gateway",
|
||||
SectionName: "same",
|
||||
},
|
||||
},
|
||||
},
|
||||
validateErr: "route parents must be unique",
|
||||
},
|
||||
"almost duplicate parents with one not specifying a listener": {
|
||||
entry: &TCPRouteConfigEntry{
|
||||
Kind: TCPRoute,
|
||||
Name: "route-two",
|
||||
Parents: []ResourceReference{
|
||||
{
|
||||
Kind: "api-gateway",
|
||||
Name: "gateway",
|
||||
},
|
||||
{
|
||||
Kind: "api-gateway",
|
||||
Name: "gateway",
|
||||
SectionName: "same",
|
||||
},
|
||||
},
|
||||
},
|
||||
check: func(t *testing.T, entry ConfigEntry) {
|
||||
expectedParents := []ResourceReference{
|
||||
{
|
||||
Kind: APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *acl.DefaultEnterpriseMeta(),
|
||||
},
|
||||
{
|
||||
Kind: APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "same",
|
||||
EnterpriseMeta: *acl.DefaultEnterpriseMeta(),
|
||||
},
|
||||
}
|
||||
route := entry.(*TCPRouteConfigEntry)
|
||||
require.Len(t, route.Parents, 2)
|
||||
require.Equal(t, expectedParents[0], route.Parents[0])
|
||||
require.Equal(t, expectedParents[1], route.Parents[1])
|
||||
},
|
||||
},
|
||||
}
|
||||
testConfigEntryNormalizeAndValidate(t, cases)
|
||||
}
|
||||
|
@ -278,7 +351,8 @@ func TestHTTPRoute(t *testing.T) {
|
|||
{
|
||||
Name: "test2",
|
||||
Weight: -1,
|
||||
}},
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
check: func(t *testing.T, entry ConfigEntry) {
|
||||
|
@ -287,6 +361,79 @@ func TestHTTPRoute(t *testing.T) {
|
|||
require.Equal(t, 1, route.Rules[0].Services[1].Weight)
|
||||
},
|
||||
},
|
||||
|
||||
"duplicate parents with no listener specified": {
|
||||
entry: &HTTPRouteConfigEntry{
|
||||
Kind: HTTPRoute,
|
||||
Name: "route-two",
|
||||
Parents: []ResourceReference{
|
||||
{
|
||||
Kind: "api-gateway",
|
||||
Name: "gateway",
|
||||
},
|
||||
{
|
||||
Kind: "api-gateway",
|
||||
Name: "gateway",
|
||||
},
|
||||
},
|
||||
},
|
||||
validateErr: "route parents must be unique",
|
||||
},
|
||||
"duplicate parents with listener specified": {
|
||||
entry: &HTTPRouteConfigEntry{
|
||||
Kind: HTTPRoute,
|
||||
Name: "route-two",
|
||||
Parents: []ResourceReference{
|
||||
{
|
||||
Kind: "api-gateway",
|
||||
Name: "gateway",
|
||||
SectionName: "same",
|
||||
},
|
||||
{
|
||||
Kind: "api-gateway",
|
||||
Name: "gateway",
|
||||
SectionName: "same",
|
||||
},
|
||||
},
|
||||
},
|
||||
validateErr: "route parents must be unique",
|
||||
},
|
||||
"almost duplicate parents with one not specifying a listener": {
|
||||
entry: &HTTPRouteConfigEntry{
|
||||
Kind: HTTPRoute,
|
||||
Name: "route-two",
|
||||
Parents: []ResourceReference{
|
||||
{
|
||||
Kind: "api-gateway",
|
||||
Name: "gateway",
|
||||
},
|
||||
{
|
||||
Kind: "api-gateway",
|
||||
Name: "gateway",
|
||||
SectionName: "same",
|
||||
},
|
||||
},
|
||||
},
|
||||
check: func(t *testing.T, entry ConfigEntry) {
|
||||
expectedParents := []ResourceReference{
|
||||
{
|
||||
Kind: APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *acl.DefaultEnterpriseMeta(),
|
||||
},
|
||||
{
|
||||
Kind: APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "same",
|
||||
EnterpriseMeta: *acl.DefaultEnterpriseMeta(),
|
||||
},
|
||||
}
|
||||
route := entry.(*HTTPRouteConfigEntry)
|
||||
require.Len(t, route.Parents, 2)
|
||||
require.Equal(t, expectedParents[0], route.Parents[0])
|
||||
require.Equal(t, expectedParents[1], route.Parents[1])
|
||||
},
|
||||
},
|
||||
}
|
||||
testConfigEntryNormalizeAndValidate(t, cases)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue