Skip to content

Commit

Permalink
fix: correctly handle route schema defaults with Konnect
Browse files Browse the repository at this point in the history
Kong Gateway supports different schemas for different router versions.
On the other hand, Konnect can support only one schema including all
fields from 'traditional' and 'expressions' router schemas.
This may be problematic when it comes to defaults injection, because
the defaults for the 'traditiona' router schema can be wrongly injected
into the 'expressions' route configuration.

Here we make sure that only the fields that are supported for a given
router version are set in the route configuration.
  • Loading branch information
GGabriele committed Feb 7, 2024
1 parent 72219d8 commit 1147ba2
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 0 deletions.
26 changes: 26 additions & 0 deletions pkg/file/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -1110,11 +1110,37 @@ func (b *stateBuilder) ingestRoute(r FRoute) error {
return err
}
r.Route.StripPath = stripPath

hasExpression := r.Route.Expression != nil
hasRegexPriority := r.Route.RegexPriority != nil
hasPathHandling := r.Route.PathHandling != nil

b.defaulter.MustSet(&r.Route)
if route != nil {
r.Route.CreatedAt = route.CreatedAt
}

// Kong Gateway supports different schemas for different router versions.
// On the other hand, Konnect can support only one schema including all
// fields from 'traditional' and 'expressions' router schemas.
// This may be problematic when it comes to defaults injection, because
// the defaults for the 'traditiona' router schema can be wrongly injected
// into the 'expressions' route configuration.
//
// Here we make sure that only the fields that are supported for a given
// router version are set in the route configuration.
if b.isKonnect && hasExpression && !(hasRegexPriority || hasPathHandling) {
if r.Route.PathHandling != nil {
r.Route.PathHandling = nil
}
if r.Route.RegexPriority != nil {
r.Route.RegexPriority = nil
}
if r.Route.Priority == nil {
r.Route.Priority = kong.Uint64(0)
}
}

b.rawState.Routes = append(b.rawState.Routes, &r.Route)
err = b.intermediate.Routes.Add(state.Route{Route: r.Route})
if err != nil {
Expand Down
90 changes: 90 additions & 0 deletions pkg/file/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2755,3 +2755,93 @@ func Test_getStripPathBasedOnProtocols(t *testing.T) {
})
}
}

func Test_stateBuilder_ingestRouteKonnect(t *testing.T) {
assert := assert.New(t)
rand.Seed(42)
type fields struct {
currentState *state.KongState
}
type args struct {
route FRoute
}
tests := []struct {
name string
fields fields
args args
wantErr bool
wantState *utils.KongRawState
}{
{
name: "traditional route",
fields: fields{
currentState: emptyState(),
},
args: args{
route: FRoute{
Route: kong.Route{
Name: kong.String("foo"),
},
},
},
wantErr: false,
wantState: &utils.KongRawState{
Routes: []*kong.Route{
{
ID: kong.String("538c7f96-b164-4f1b-97bb-9f4bb472e89f"),
Name: kong.String("foo"),
PreserveHost: kong.Bool(false),
RegexPriority: kong.Int(0),
StripPath: kong.Bool(false),
Protocols: kong.StringSlice("http", "https"),
},
},
},
},
{
name: "expression route",
fields: fields{
currentState: emptyState(),
},
args: args{
route: FRoute{
Route: kong.Route{
Name: kong.String("foo"),
Expression: kong.String(`'(http.path == "/test") || (http.path ^= "/test/")'`),
},
},
},
wantErr: false,
wantState: &utils.KongRawState{
Routes: []*kong.Route{
{
ID: kong.String("5b1484f2-5209-49d9-b43e-92ba09dd9d52"),
Name: kong.String("foo"),
PreserveHost: kong.Bool(false),
Expression: kong.String(`'(http.path == "/test") || (http.path ^= "/test/")'`),
Priority: kong.Uint64(0),
StripPath: kong.Bool(false),
Protocols: kong.StringSlice("http", "https"),
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
b := &stateBuilder{
currentState: tt.fields.currentState,
isKonnect: true,
}
b.rawState = &utils.KongRawState{}
d, _ := utils.GetDefaulter(ctx, defaulterTestOpts)
b.defaulter = d
b.intermediate, _ = state.NewKongState()
if err := b.ingestRoute(tt.args.route); (err != nil) != tt.wantErr {
t.Errorf("stateBuilder.ingestRoute() error = %v, wantErr %v", err, tt.wantErr)
}
assert.Equal(tt.wantState, b.rawState)
})
}
}

0 comments on commit 1147ba2

Please sign in to comment.