Skip to content
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 .github/workflows/conformance-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ jobs:
continue-on-error: true
run: |
make conformance-test
- name: Get Logs from api7-ingress-controller
shell: bash
run: |
export KUBECONFIG=/tmp/api7-ingress-cluster.kubeconfig
kubectl logs -n api7ee-conformance-test -l app=api7-ingress-controller
- name: Upload Gateway API Conformance Report
if: ${{ github.event_name == 'push' }}
Expand Down
9 changes: 3 additions & 6 deletions internal/provider/adc/cache/cache.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
Expand Down
15 changes: 0 additions & 15 deletions internal/provider/adc/cache/memdb.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,3 @@
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cache

import (
Expand Down
15 changes: 0 additions & 15 deletions internal/provider/adc/cache/schema.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,3 @@
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cache

import (
Expand Down
5 changes: 3 additions & 2 deletions internal/provider/adc/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,11 @@ func (s *Store) Delete(name string, resourceTypes []string, Labels map[string]st
delete(s.globalruleMap, name)
case "plugin_metadata":
delete(s.pluginMetadataMap, name)
default:
delete(s.cacheMap, name)
}
}
if len(resourceTypes) == 0 {
delete(s.cacheMap, name)
}
return nil
}

Expand Down
78 changes: 51 additions & 27 deletions internal/provider/adc/translator/httproute.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ package translator
import (
"encoding/json"
"fmt"
"sort"
"strings"

"github.com/api7/gopkg/pkg/log"
Expand Down Expand Up @@ -354,31 +353,61 @@ func (t *Translator) translateBackendRef(tctx *provider.TranslateContext, ref ga
return t.translateEndpointSlice(portName, weight, endpointSlices)
}

// calculateMatchPriority calculate the priority of HTTPRouteMatch, according to the Gateway API specification
// the higher the return value, the higher the priority
func calculateMatchPriority(match *gatewayv1.HTTPRouteMatch) int64 {
var score int64 = 0
// calculateHTTPRoutePriority calculates the priority of the HTTP route.
// ref: https://github.com/Kong/kubernetes-ingress-controller/blob/57472721319e2c63e56cb8540425257e8e02520f/internal/dataplane/translator/subtranslator/httproute_atc.go#L279-L296
func calculateHTTPRoutePriority(match *gatewayv1.HTTPRouteMatch, ruleIndex int) uint64 {
const (
// ExactPathShiftBits assigns bit 34 to mark if the match is exact path match.
ExactPathShiftBits = 34
// PathLengthShiftBits assigns bits 23-32 to path length. (max length = 1024, but must start with /)
PathLengthShiftBits = 23
// MethodMatchShiftBits assigns bit 22 to mark if method is specified.
MethodMatchShiftBits = 22
// HeaderNumberShiftBits assign bits 17-21 to number of headers. (max number of headers = 16)
HeaderNumberShiftBits = 17
// QueryParamNumberShiftBits makes bits 12-16 used for number of query params (max number of query params = 16)
QueryParamNumberShiftBits = 12
// RuleIndexShiftBits assigns bits 7-11 to rule index. (max number of rules = 16)
RuleIndexShiftBits = 7
)

var priority uint64 = 0

// 1. Exact path matches have the highest priority
// ExactPathShiftBits
if match.Path != nil && match.Path.Type != nil && *match.Path.Type == gatewayv1.PathMatchExact {
score += 10000
} else if match.Path != nil && match.Path.Type != nil && *match.Path.Type == gatewayv1.PathMatchPathPrefix && match.Path.Value != nil {
// 2. Prefix path matches, the longer the string, the higher the priority
score += 1000 + int64(len(*match.Path.Value))
priority |= (1 << ExactPathShiftBits)
}

// PathLengthShiftBits
// max length of path is 1024, but path must start with /, so we use PathLength-1 to fill the bits.
if match.Path != nil && match.Path.Value != nil {
pathLength := len(*match.Path.Value)
if pathLength > 0 {
priority |= (uint64(pathLength-1) << PathLengthShiftBits)
}
}

// 3. Method matching
// MethodMatchShiftBits
if match.Method != nil {
score += 100
priority |= (1 << MethodMatchShiftBits)
}

// 4. Header matching, the more headers, the higher the priority
score += int64(len(match.Headers) * 10)
// HeaderNumberShiftBits
headerCount := len(match.Headers)
priority |= (uint64(headerCount) << HeaderNumberShiftBits)

// 5. Query parameter matching, the more query parameters, the higher the priority
score += int64(len(match.QueryParams))
// QueryParamNumberShiftBits
queryParamCount := len(match.QueryParams)
priority |= (uint64(queryParamCount) << QueryParamNumberShiftBits)

return score
// RuleIndexShiftBits
index := 16 - ruleIndex
if index < 0 {
index = 0
}
priority |= (uint64(index) << RuleIndexShiftBits)

return priority
}

func (t *Translator) TranslateHTTPRoute(tctx *provider.TranslateContext, httpRoute *gatewayv1.HTTPRoute) (*TranslateResult, error) {
Expand All @@ -393,7 +422,7 @@ func (t *Translator) TranslateHTTPRoute(tctx *provider.TranslateContext, httpRou

labels := label.GenLabel(httpRoute)

for i, rule := range rules {
for ruleIndex, rule := range rules {
upstream := adctypes.NewDefaultUpstream()
for _, backend := range rule.BackendRefs {
if backend.Namespace == nil {
Expand All @@ -410,7 +439,7 @@ func (t *Translator) TranslateHTTPRoute(tctx *provider.TranslateContext, httpRou
service := adctypes.NewDefaultService()
service.Labels = labels

service.Name = adctypes.ComposeServiceNameWithRule(httpRoute.Namespace, httpRoute.Name, fmt.Sprintf("%d", i))
service.Name = adctypes.ComposeServiceNameWithRule(httpRoute.Namespace, httpRoute.Name, fmt.Sprintf("%d", ruleIndex))
service.ID = id.GenID(service.Name)
service.Hosts = hosts
service.Upstream = upstream
Expand All @@ -428,11 +457,6 @@ func (t *Translator) TranslateHTTPRoute(tctx *provider.TranslateContext, httpRou
},
},
}
} else {
// Sort the matches by priority
sort.Slice(matches, func(a, b int) bool {
return calculateMatchPriority(&matches[a]) > calculateMatchPriority(&matches[b])
})
}

routes := []*adctypes.Route{}
Expand All @@ -442,15 +466,15 @@ func (t *Translator) TranslateHTTPRoute(tctx *provider.TranslateContext, httpRou
return nil, err
}

name := adctypes.ComposeRouteName(httpRoute.Namespace, httpRoute.Name, fmt.Sprintf("%d-%d", i, j))
name := adctypes.ComposeRouteName(httpRoute.Namespace, httpRoute.Name, fmt.Sprintf("%d-%d", ruleIndex, j))
route.Name = name
route.ID = id.GenID(name)
route.Labels = labels
route.EnableWebsocket = ptr.To(true)

// Set the route priority
priority := calculateMatchPriority(&match)
route.Priority = &priority
priority := calculateHTTPRoutePriority(&match, ruleIndex)
route.Priority = ptr.To(int64(priority))

routes = append(routes, route)
}
Expand Down
12 changes: 12 additions & 0 deletions test/conformance/suite_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package conformance

import (
Expand Down Expand Up @@ -149,6 +160,7 @@ func TestMain(m *testing.M) {
Namespace: namespace,
AdminEnpoint: framework.DashboardTLSEndpoint,
StatusAddress: address,
InitSyncDelay: 30 * time.Minute,
})

defaultGatewayProxyOpts = GatewayProxyOpts{
Expand Down
1 change: 1 addition & 0 deletions test/e2e/framework/ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type IngressDeployOpts struct {
AdminEnpoint string
StatusAddress string
Replicas int
InitSyncDelay time.Duration
}

func (f *Framework) DeployIngress(opts IngressDeployOpts) {
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/framework/manifests/ingress.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ data:
# The period between two consecutive syncs.
# The default value is 0 seconds, which means the controller will not sync.
# If you want to enable the sync, set it to a positive value.
init_sync_delay: 1m
init_sync_delay: {{ .InitSyncDelay | default "1m" }}
---
apiVersion: v1
kind: Service
Expand Down
Loading