Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ GATEAY_API_VERSION ?= v1.3.0
SUPPORTED_EXTENDED_FEATURES = "HTTPRouteDestinationPortMatching,HTTPRouteMethodMatching,HTTPRoutePortRedirect,HTTPRouteRequestMirror,HTTPRouteSchemeRedirect,GatewayAddressEmpty,HTTPRouteResponseHeaderModification,GatewayPort8080"
CONFORMANCE_TEST_REPORT_OUTPUT ?= $(DIR)/apisix-ingress-controller-conformance-report.yaml
## https://github.com/kubernetes-sigs/gateway-api/blob/v1.3.0/conformance/utils/suite/profiles.go
CONFORMANCE_PROFILES ?= GATEWAY-HTTP,GATEWAY-GRPC
CONFORMANCE_PROFILES ?= GATEWAY-HTTP,GATEWAY-GRPC,GATEWAY-TLS

# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
Expand Down
2 changes: 2 additions & 0 deletions api/v2/shared_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ const (
SchemeTCP = "tcp"
// SchemeUDP represents the UDP protocol.
SchemeUDP = "udp"
// SchemeTLS represents the TLS protocol.
SchemeTLS = "tls"
)

const (
Expand Down
2 changes: 2 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ rules:
- httproutes/status
- referencegrants/status
- tcproutes/status
- tlsroutes/status
- udproutes/status
verbs:
- get
Expand All @@ -105,6 +106,7 @@ rules:
- httproutes
- referencegrants
- tcproutes
- tlsroutes
- udproutes
verbs:
- get
Expand Down
2 changes: 1 addition & 1 deletion docs/en/latest/concepts/gateway-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ By supporting Gateway API, the APISIX Ingress controller can realize richer func
| HTTPRoute | Supported | Partially supported | Not supported | v1 |
| GRPCRoute | Supported | Supported | Not supported | v1 |
| ReferenceGrant | Supported | Not supported | Not supported | v1beta1 |
| TLSRoute | Not supported | Not supported | Not supported | v1alpha2 |
| TLSRoute | Supported | Supported | Not supported | v1alpha2 |
| TCPRoute | Supported | Supported | Not supported | v1alpha2 |
| UDPRoute | Supported | Supported | Not supported | v1alpha2 |
| BackendTLSPolicy | Not supported | Not supported | Not supported | v1alpha3 |
Expand Down
160 changes: 160 additions & 0 deletions internal/adc/translator/tlsroute.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
// 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 translator

import (
"fmt"

gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"

adctypes "github.com/apache/apisix-ingress-controller/api/adc"
apiv2 "github.com/apache/apisix-ingress-controller/api/v2"
"github.com/apache/apisix-ingress-controller/internal/controller/label"
"github.com/apache/apisix-ingress-controller/internal/id"
"github.com/apache/apisix-ingress-controller/internal/provider"
"github.com/apache/apisix-ingress-controller/internal/types"
)

func (t *Translator) TranslateTLSRoute(tctx *provider.TranslateContext, tlsRoute *gatewayv1alpha2.TLSRoute) (*TranslateResult, error) {
result := &TranslateResult{}
rules := tlsRoute.Spec.Rules
labels := label.GenLabel(tlsRoute)
hosts := make([]string, 0, len(tlsRoute.Spec.Hostnames))
for _, hostname := range tlsRoute.Spec.Hostnames {
hosts = append(hosts, string(hostname))
}
for ruleIndex, rule := range rules {
service := adctypes.NewDefaultService()
service.Labels = labels
service.Name = adctypes.ComposeServiceNameWithStream(tlsRoute.Namespace, tlsRoute.Name, fmt.Sprintf("%d", ruleIndex), "TLS")
service.ID = id.GenID(service.Name)
var (
upstreams = make([]*adctypes.Upstream, 0)
weightedUpstreams = make([]adctypes.TrafficSplitConfigRuleWeightedUpstream, 0)
)
for _, backend := range rule.BackendRefs {
if backend.Namespace == nil {
namespace := gatewayv1.Namespace(tlsRoute.Namespace)
backend.Namespace = &namespace
}
upstream := newDefaultUpstreamWithoutScheme()
upNodes, err := t.translateBackendRef(tctx, backend, DefaultEndpointFilter)
if err != nil {
continue
}
if len(upNodes) == 0 {
continue
}
// TODO: Confirm BackendTrafficPolicy attachment with e2e test case.
t.AttachBackendTrafficPolicyToUpstream(backend, tctx.BackendTrafficPolicies, upstream)
upstream.Nodes = upNodes
var (
kind string
port int32
)
if backend.Kind == nil {
kind = types.KindService
} else {
kind = string(*backend.Kind)
}
if backend.Port != nil {
port = int32(*backend.Port)
}
namespace := string(*backend.Namespace)
name := string(backend.Name)
upstreamName := adctypes.ComposeUpstreamNameForBackendRef(kind, namespace, name, port)
upstream.Name = upstreamName
upstream.ID = id.GenID(upstreamName)
upstreams = append(upstreams, upstream)
}

// Handle multiple backends with traffic-split plugin
if len(upstreams) == 0 {
// Create a default upstream if no valid backends
upstream := adctypes.NewDefaultUpstream()
service.Upstream = upstream
} else if len(upstreams) == 1 {
// Single backend - use directly as service upstream
service.Upstream = upstreams[0]
// remove the id and name of the service.upstream, adc schema does not need id and name for it
service.Upstream.ID = ""
service.Upstream.Name = ""
} else {
// Multiple backends - use traffic-split plugin
service.Upstream = upstreams[0]
// remove the id and name of the service.upstream, adc schema does not need id and name for it
service.Upstream.ID = ""
service.Upstream.Name = ""

upstreams = upstreams[1:]

if len(upstreams) > 0 {
service.Upstreams = upstreams
}

// Set weight in traffic-split for the default upstream
weight := apiv2.DefaultWeight
if rule.BackendRefs[0].Weight != nil {
weight = int(*rule.BackendRefs[0].Weight)
}
weightedUpstreams = append(weightedUpstreams, adctypes.TrafficSplitConfigRuleWeightedUpstream{
Weight: weight,
})

// Set other upstreams in traffic-split using upstream_id
for i, upstream := range upstreams {
weight := apiv2.DefaultWeight
// get weight from the backend refs starting from the second backend
if i+1 < len(rule.BackendRefs) && rule.BackendRefs[i+1].Weight != nil {
weight = int(*rule.BackendRefs[i+1].Weight)
}
weightedUpstreams = append(weightedUpstreams, adctypes.TrafficSplitConfigRuleWeightedUpstream{
UpstreamID: upstream.ID,
Weight: weight,
})
}

if len(weightedUpstreams) > 0 {
if service.Plugins == nil {
service.Plugins = make(map[string]any)
}
service.Plugins["traffic-split"] = &adctypes.TrafficSplitConfig{
Rules: []adctypes.TrafficSplitConfigRule{
{
WeightedUpstreams: weightedUpstreams,
},
},
}
}
}

for _, host := range hosts {
streamRoute := adctypes.NewDefaultStreamRoute()
streamRouteName := adctypes.ComposeStreamRouteName(tlsRoute.Namespace, tlsRoute.Name, fmt.Sprintf("%d", ruleIndex), "TLS")
streamRoute.Name = streamRouteName
streamRoute.ID = id.GenID(streamRouteName)
streamRoute.SNI = host
streamRoute.Labels = labels
service.StreamRoutes = append(service.StreamRoutes, streamRoute)

}
result.Services = append(result.Services, service)
}
return result, nil
}
1 change: 1 addition & 0 deletions internal/controller/indexer/indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ func SetupIndexer(mgr ctrl.Manager) error {
setupTCPRouteIndexer,
setupUDPRouteIndexer,
setupGRPCRouteIndexer,
setupTLSRouteIndexer,
setupIngressIndexer,
setupConsumerIndexer,
setupBackendTrafficPolicyIndexer,
Expand Down
79 changes: 79 additions & 0 deletions internal/controller/indexer/tlsroute.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// 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 indexer

import (
"context"

internaltypes "github.com/apache/apisix-ingress-controller/internal/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
)

func setupTLSRouteIndexer(mgr ctrl.Manager) error {
if err := mgr.GetFieldIndexer().IndexField(
context.Background(),
&gatewayv1alpha2.TLSRoute{},
ParentRefs,
TLSRouteParentRefsIndexFunc,
); err != nil {
return err
}

if err := mgr.GetFieldIndexer().IndexField(
context.Background(),
&gatewayv1alpha2.TLSRoute{},
ServiceIndexRef,
TLSPRouteServiceIndexFunc,
); err != nil {
return err
}
return nil
}

func TLSRouteParentRefsIndexFunc(rawObj client.Object) []string {
tr := rawObj.(*gatewayv1alpha2.TLSRoute)
keys := make([]string, 0, len(tr.Spec.ParentRefs))
for _, ref := range tr.Spec.ParentRefs {
ns := tr.GetNamespace()
if ref.Namespace != nil {
ns = string(*ref.Namespace)
}
keys = append(keys, GenIndexKey(ns, string(ref.Name)))
}
return keys
}

func TLSPRouteServiceIndexFunc(rawObj client.Object) []string {
tr := rawObj.(*gatewayv1alpha2.TLSRoute)
keys := make([]string, 0, len(tr.Spec.Rules))
for _, rule := range tr.Spec.Rules {
for _, backend := range rule.BackendRefs {
namespace := tr.GetNamespace()
if backend.Kind != nil && *backend.Kind != internaltypes.KindService {
continue
}
if backend.Namespace != nil {
namespace = string(*backend.Namespace)
}
keys = append(keys, GenIndexKey(namespace, string(backend.Name)))
}
}
return keys
}
Loading
Loading