Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
23 changes: 11 additions & 12 deletions internal/controller/httproute_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,14 +397,20 @@ func (r *HTTPRouteReconciler) processHTTPRouteBackendRefs(tctx *provider.Transla
continue
}

var service corev1.Service
if err := r.Get(tctx, client.ObjectKey{
serviceNS := types.NamespacedName{
Namespace: namespace,
Name: name,
}, &service); err != nil {
}

var service corev1.Service
if err := r.Get(tctx, serviceNS, &service); err != nil {
terr = err
continue
}
if service.Spec.Type == corev1.ServiceTypeExternalName {
tctx.Services[serviceNS] = &service
return nil
}

portExists := false
for _, port := range service.Spec.Ports {
Expand All @@ -417,10 +423,7 @@ func (r *HTTPRouteReconciler) processHTTPRouteBackendRefs(tctx *provider.Transla
terr = fmt.Errorf("port %d not found in service %s", *backend.Port, name)
continue
}
tctx.Services[client.ObjectKey{
Namespace: namespace,
Name: name,
}] = &service
tctx.Services[serviceNS] = &service

endpointSliceList := new(discoveryv1.EndpointSliceList)
if err := r.List(tctx, endpointSliceList,
Expand All @@ -434,11 +437,7 @@ func (r *HTTPRouteReconciler) processHTTPRouteBackendRefs(tctx *provider.Transla
continue
}

tctx.EndpointSlices[client.ObjectKey{
Namespace: namespace,
Name: name,
}] = endpointSliceList.Items

tctx.EndpointSlices[serviceNS] = endpointSliceList.Items
}
return terr
}
Expand Down
22 changes: 10 additions & 12 deletions internal/controller/ingress_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -522,17 +522,23 @@ func (r *IngressReconciler) processBackends(tctx *provider.TranslateContext, ing
func (r *IngressReconciler) processBackendService(tctx *provider.TranslateContext, namespace string, backendService *networkingv1.IngressServiceBackend) error {
// get the service
var service corev1.Service
if err := r.Get(tctx, client.ObjectKey{
serviceNS := types.NamespacedName{
Namespace: namespace,
Name: backendService.Name,
}, &service); err != nil {
}
if err := r.Get(tctx, serviceNS, &service); err != nil {
if client.IgnoreNotFound(err) == nil {
r.Log.Info("service not found", "namespace", namespace, "name", backendService.Name)
return nil
}
return err
}

if service.Spec.Type == corev1.ServiceTypeExternalName {
tctx.Services[serviceNS] = &service
return nil
}

// verify if the port exists
var portExists bool
if backendService.Port.Number != 0 {
Expand Down Expand Up @@ -570,16 +576,8 @@ func (r *IngressReconciler) processBackendService(tctx *provider.TranslateContex
}

// save the endpoint slices to the translate context
tctx.EndpointSlices[client.ObjectKey{
Namespace: namespace,
Name: backendService.Name,
}] = endpointSliceList.Items

tctx.Services[client.ObjectKey{
Namespace: namespace,
Name: backendService.Name,
}] = &service

tctx.EndpointSlices[serviceNS] = endpointSliceList.Items
tctx.Services[serviceNS] = &service
return nil
}

Expand Down
33 changes: 25 additions & 8 deletions internal/provider/adc/translator/httproute.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ import (
"fmt"
"strings"

"github.com/api7/gopkg/pkg/log"
"github.com/pkg/errors"
"go.uber.org/zap"
corev1 "k8s.io/api/core/v1"
discoveryv1 "k8s.io/api/discovery/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/utils/ptr"
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"

"github.com/api7/api7-ingress-controller/api/v1alpha1"
"github.com/api7/gopkg/pkg/log"

adctypes "github.com/api7/api7-ingress-controller/api/adc"
"github.com/api7/api7-ingress-controller/api/v1alpha1"
"github.com/api7/api7-ingress-controller/internal/controller/label"
"github.com/api7/api7-ingress-controller/internal/id"
"github.com/api7/api7-ingress-controller/internal/provider"
Expand Down Expand Up @@ -289,16 +289,33 @@ func (t *Translator) translateEndpointSlice(weight int, endpointSlices []discove
}

func (t *Translator) translateBackendRef(tctx *provider.TranslateContext, ref gatewayv1.BackendRef) adctypes.UpstreamNodes {
endpointSlices := tctx.EndpointSlices[types.NamespacedName{
Namespace: string(*ref.Namespace),
Name: string(ref.Name),
}]

weight := 1
port := 80
if ref.Weight != nil {
weight = int(*ref.Weight)
}
if ref.Port != nil {
port = int(*ref.Port)
}
key := types.NamespacedName{
Namespace: string(*ref.Namespace),
Name: string(ref.Name),
}
service, ok := tctx.Services[key]
if !ok {
return adctypes.UpstreamNodes{}
}

if service.Spec.Type == corev1.ServiceTypeExternalName {
return adctypes.UpstreamNodes{
{
Host: service.Spec.ExternalName,
Port: port,
Weight: weight,
},
}
}
endpointSlices := tctx.EndpointSlices[key]
return t.translateEndpointSlice(weight, endpointSlices)
}

Expand Down
52 changes: 27 additions & 25 deletions internal/provider/adc/translator/ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,7 @@ func (t *Translator) TranslateIngress(tctx *provider.TranslateContext, obj *netw

// get the EndpointSlice of the backend service
backendService := path.Backend.Service
var endpointSlices []discoveryv1.EndpointSlice
if backendService != nil {
endpointSlices = tctx.EndpointSlices[types.NamespacedName{
Namespace: obj.Namespace,
Name: backendService.Name,
}]
backendRef := convertBackendRef(obj.Namespace, backendService.Name, "Service")
t.AttachBackendTrafficPolicyToUpstream(backendRef, tctx.BackendTrafficPolicies, upstream)
}
Expand All @@ -131,28 +126,35 @@ func (t *Translator) TranslateIngress(tctx *provider.TranslateContext, obj *netw
if getService == nil {
continue
}

var getServicePort *corev1.ServicePort
for _, port := range getService.Spec.Ports {
port := port
if servicePort > 0 && port.Port == servicePort {
getServicePort = &port
break
if getService.Spec.Type == corev1.ServiceTypeExternalName {
upstream.Nodes = adctypes.UpstreamNodes{
{
Host: getService.Spec.ExternalName,
Port: int(servicePort),
Weight: 1,
},
}
if servicePortName != "" && port.Name == servicePortName {
getServicePort = &port
break
} else {
var getServicePort *corev1.ServicePort
for _, port := range getService.Spec.Ports {
port := port
if servicePort > 0 && port.Port == servicePort {
getServicePort = &port
break
}
if servicePortName != "" && port.Name == servicePortName {
getServicePort = &port
break
}
}
endpointSlices := tctx.EndpointSlices[types.NamespacedName{
Namespace: obj.Namespace,
Name: backendService.Name,
}]
// convert the EndpointSlice to upstream nodes
if len(endpointSlices) > 0 {
upstream.Nodes = t.translateEndpointSliceForIngress(1, endpointSlices, getServicePort)
}
}

// convert the EndpointSlice to upstream nodes
if len(endpointSlices) > 0 {
upstream.Nodes = t.translateEndpointSliceForIngress(1, endpointSlices, getServicePort)
}

// if there is no upstream node, create a placeholder node
if len(upstream.Nodes) == 0 {
upstream.Nodes = adctypes.UpstreamNodes{}
}

service.Upstream = upstream
Expand Down
39 changes: 39 additions & 0 deletions test/e2e/gatewayapi/httproute.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,33 @@ spec:
})

Context("HTTPRoute Base", func() {
var httprouteWithExternalName = `
apiVersion: v1
kind: Service
metadata:
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httpbin
spec:
parentRefs:
- name: api7ee
hostnames:
- httpbin.external
rules:
- matches:
- path:
type: Exact
value: /get
backendRefs:
- name: httpbin-external-domain
port: 80
`
var exactRouteByGet = `
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
Expand Down Expand Up @@ -437,6 +464,18 @@ spec:
Expect().
Status(404)
})

It("Proxy external service", func() {
By("create HTTPRoute")
ResourceApplied("HTTPRoute", "httpbin", httprouteWithExternalName, 1)

By("checking the external service response")
s.NewAPISIXClient().
GET("/get").
WithHost("httpbin.external").
Expect().
Status(200)
})
})
Context("HTTPRoute Rule Match", func() {
var exactRouteByGet = `
Expand Down
54 changes: 54 additions & 0 deletions test/e2e/ingress/ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,33 @@ spec:
number: 80
`

var ingressWithExternalName = `
apiVersion: v1
kind: Service
metadata:
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api7-ingress-default
spec:
rules:
- host: httpbin.external
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: httpbin-external-domain
port:
number: 80
`

It("Test IngressClass Selection", func() {
By("create GatewayProxy")
gatewayProxy := fmt.Sprintf(gatewayProxyYaml, framework.DashboardTLSEndpoint, s.AdminKey())
Expand All @@ -184,6 +211,33 @@ spec:
Expect().
Status(200)
})

It("Proxy external service", func() {
By("create GatewayProxy")
gatewayProxy := fmt.Sprintf(gatewayProxyYaml, framework.DashboardTLSEndpoint, s.AdminKey())

By("create GatewayProxy")
err := s.CreateResourceFromStringWithNamespace(gatewayProxy, "default")
Expect(err).NotTo(HaveOccurred(), "creating GatewayProxy")
time.Sleep(5 * time.Second)

By("create Default IngressClass")
err = s.CreateResourceFromStringWithNamespace(defaultIngressClass, "")
Expect(err).NotTo(HaveOccurred(), "creating Default IngressClass")
time.Sleep(5 * time.Second)

By("create Ingress")
err = s.CreateResourceFromString(ingressWithExternalName)
Expect(err).NotTo(HaveOccurred(), "creating Ingress without IngressClass")
time.Sleep(5 * time.Second)

By("checking the external service response")
s.NewAPISIXClient().
GET("/get").
WithHost("httpbin.external").
Expect().
Status(200)
})
})

Context("IngressClass with GatewayProxy", func() {
Expand Down
Loading