Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new konghq.com/regex-priority annotation #591

Merged
merged 3 commits into from
Apr 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions internal/ingress/annotations/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const (
pathKey = "/path"
httpsRedirectCodeKey = "/https-redirect-status-code"
preserveHostKey = "/preserve-host"
regexPriorityKey = "/regex-priority"

// DefaultIngressClass defines the default class used
// by Kong's ingress controller.
Expand Down Expand Up @@ -177,3 +178,8 @@ func ExtractPreserveHost(anns map[string]string) string {
func HasServiceUpstreamAnnotation(anns map[string]string) bool {
return anns["ingress.kubernetes.io/service-upstream"] == "true"
}

// ExtractRegexPriority extracts the regex-priority annotation value.
func ExtractRegexPriority(anns map[string]string) string {
return valueFromAnnotation(regexPriorityKey, anns)
}
51 changes: 51 additions & 0 deletions internal/ingress/annotations/annotations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -570,3 +570,54 @@ func TestExtractPreserveHost(t *testing.T) {
})
}
}

func TestExtractRegexPriority(t *testing.T) {
type args struct {
anns map[string]string
}
tests := []struct {
name string
args args
want string
}{
{
name: "empty",
want: "",
},
{
name: "non-empty old group",
args: args{
anns: map[string]string{
"configuration.konghq.com/regex-priority": "5",
},
},
want: "5",
},
{
name: "non-empty new group",
args: args{
anns: map[string]string{
"konghq.com/regex-priority": "10",
},
},
want: "10",
},
{
name: "group preference",
args: args{
anns: map[string]string{
"configuration.konghq.com/regex-priority": "5",
"konghq.com/regex-priority": "10",
},
},
want: "10",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := ExtractRegexPriority(tt.args.anns); got != tt.want {
t.Errorf("ExtractRegexPriority() = %v, want %v", got, tt.want)
}
})
}
}
14 changes: 14 additions & 0 deletions internal/ingress/controller/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -1063,6 +1063,19 @@ func overrideRoutePreserveHost(route *kong.Route, anns map[string]string) {
}
}

func overrideRouteRegexPriority(route *kong.Route, anns map[string]string) {
priority := annotations.ExtractRegexPriority(anns)
if priority == "" {
return
}
regexPriority, err := strconv.Atoi(priority)
if err != nil {
return
}

route.RegexPriority = kong.Int(regexPriority)
}

// overrideRouteByAnnotation sets Route protocols via annotation
func overrideRouteByAnnotation(route *Route) {
anns := route.Ingress.Annotations
Expand All @@ -1073,6 +1086,7 @@ func overrideRouteByAnnotation(route *Route) {
overrideRouteStripPath(&route.Route, anns)
overrideRouteHTTPSRedirectCode(&route.Route, anns)
overrideRoutePreserveHost(&route.Route, anns)
overrideRouteRegexPriority(&route.Route, anns)
}

// overrideRoute sets Route fields by KongIngress first, then by annotation
Expand Down
229 changes: 229 additions & 0 deletions internal/ingress/controller/parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,162 @@ func TestKongRouteAnnotations(t *testing.T) {
RegexPriority: kong.Int(0),
}, state.Services[0].Routes[0].Route)
})
t.Run("regex-priority annotation is correctly processed",
func(t *testing.T) {
ingresses := []*networking.Ingress{
{
ObjectMeta: metav1.ObjectMeta{
Name: "bar",
Namespace: "default",
Annotations: map[string]string{
"konghq.com/regex-priority": "10",
},
},
Spec: networking.IngressSpec{
Rules: []networking.IngressRule{
{
Host: "example.com",
IngressRuleValue: networking.IngressRuleValue{
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{
{
Path: "/",
Backend: networking.IngressBackend{
ServiceName: "foo-svc",
ServicePort: intstr.FromInt(80),
},
},
},
},
},
},
},
},
},
}

services := []*corev1.Service{
{
ObjectMeta: metav1.ObjectMeta{
Name: "foo-svc",
Namespace: "default",
},
},
}
store, err := store.NewFakeStore(store.FakeObjects{
Ingresses: ingresses,
Services: services,
})
assert.Nil(err)
parser := New(store)
state, err := parser.Build()
assert.Nil(err)
assert.NotNil(state)

assert.Equal(1, len(state.Services),
"expected one service to be rendered")
assert.Equal(kong.Service{
Name: kong.String("default.foo-svc.80"),
Host: kong.String("foo-svc.default.80.svc"),
Path: kong.String("/"),
Port: kong.Int(80),
ConnectTimeout: kong.Int(60000),
ReadTimeout: kong.Int(60000),
WriteTimeout: kong.Int(60000),
Retries: kong.Int(5),
Protocol: kong.String("http"),
}, state.Services[0].Service)

assert.Equal(1, len(state.Services[0].Routes),
"expected one route to be rendered")
assert.Equal(kong.Route{
Name: kong.String("default.bar.00"),
StripPath: kong.Bool(false),
RegexPriority: kong.Int(10),
Hosts: kong.StringSlice("example.com"),
PreserveHost: kong.Bool(true),
Paths: kong.StringSlice("/"),
Protocols: kong.StringSlice("http", "https"),
}, state.Services[0].Routes[0].Route)
})
t.Run("non-integer regex-priority annotation is ignored",
func(t *testing.T) {
ingresses := []*networking.Ingress{
{
ObjectMeta: metav1.ObjectMeta{
Name: "bar",
Namespace: "default",
Annotations: map[string]string{
"konghq.com/regex-priority": "IAmAString",
},
},
Spec: networking.IngressSpec{
Rules: []networking.IngressRule{
{
Host: "example.com",
IngressRuleValue: networking.IngressRuleValue{
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{
{
Path: "/",
Backend: networking.IngressBackend{
ServiceName: "foo-svc",
ServicePort: intstr.FromInt(80),
},
},
},
},
},
},
},
},
},
}

services := []*corev1.Service{
{
ObjectMeta: metav1.ObjectMeta{
Name: "foo-svc",
Namespace: "default",
},
},
}
store, err := store.NewFakeStore(store.FakeObjects{
Ingresses: ingresses,
Services: services,
})
assert.Nil(err)
parser := New(store)
state, err := parser.Build()
assert.Nil(err)
assert.NotNil(state)

assert.Equal(1, len(state.Services),
"expected one service to be rendered")
assert.Equal(kong.Service{
Name: kong.String("default.foo-svc.80"),
Host: kong.String("foo-svc.default.80.svc"),
Path: kong.String("/"),
Port: kong.Int(80),
ConnectTimeout: kong.Int(60000),
ReadTimeout: kong.Int(60000),
WriteTimeout: kong.Int(60000),
Retries: kong.Int(5),
Protocol: kong.String("http"),
}, state.Services[0].Service)

assert.Equal(1, len(state.Services[0].Routes),
"expected one route to be rendered")
assert.Equal(kong.Route{
Name: kong.String("default.bar.00"),
StripPath: kong.Bool(false),
RegexPriority: kong.Int(0),
Hosts: kong.StringSlice("example.com"),
PreserveHost: kong.Bool(true),
Paths: kong.StringSlice("/"),
Protocols: kong.StringSlice("http", "https"),
}, state.Services[0].Routes[0].Route)
})
}

func TestKnativeIngressAndPlugins(t *testing.T) {
Expand Down Expand Up @@ -4317,6 +4473,79 @@ func Test_overrideRoutePreserveHost(t *testing.T) {
}
}

func Test_overrideRouteRegexPriority(t *testing.T) {
type args struct {
route *kong.Route
anns map[string]string
}
tests := []struct {
name string
args args
want *kong.Route
}{
{},
{
name: "basic empty route",
args: args{
route: &kong.Route{},
},
want: &kong.Route{},
},
{
name: "basic sanity",
args: args{
route: &kong.Route{},
anns: map[string]string{
"konghq.com/regex-priority": "10",
},
},
want: &kong.Route{
RegexPriority: kong.Int(10),
},
},
{
name: "negative integer",
args: args{
route: &kong.Route{},
anns: map[string]string{
"konghq.com/regex-priority": "-10",
},
},
want: &kong.Route{
RegexPriority: kong.Int(-10),
},
},
{
name: "random float value",
args: args{
route: &kong.Route{},
anns: map[string]string{
"konghq.com/regex-priority": "42.42",
},
},
want: &kong.Route{},
},
{
name: "random string",
args: args{
route: &kong.Route{},
anns: map[string]string{
"konghq.com/regex-priority": "foo",
},
},
want: &kong.Route{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
overrideRouteRegexPriority(tt.args.route, tt.args.anns)
if !reflect.DeepEqual(tt.args.route, tt.want) {
t.Errorf("overrideRouteRegexPriority() got = %v, want %v", tt.args.route, tt.want)
}
})
}
rainest marked this conversation as resolved.
Show resolved Hide resolved
}

func Test_knativeSelectSplit(t *testing.T) {
type args struct {
splits []knative.IngressBackendSplit
Expand Down