Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
11 changes: 11 additions & 0 deletions internal/provider/adc/cache/indexer.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 cache

import (
Expand Down
12 changes: 4 additions & 8 deletions internal/provider/adc/cache/memdb.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
// 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
// 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
11 changes: 11 additions & 0 deletions internal/provider/adc/cache/noop_db.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 cache

import (
Expand Down
12 changes: 4 additions & 8 deletions internal/provider/adc/cache/schema.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
// 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
// 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
16 changes: 14 additions & 2 deletions internal/provider/adc/store.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 adc

import (
Expand Down Expand Up @@ -151,10 +162,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: 1 * 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