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

feat: add support of KongServiceFacade as default Ingress backend #5282

Merged
merged 2 commits into from
Dec 5, 2023
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ Adding a new version? You'll need three changes:
When installed, it has to be enabled with `ServiceFacade` feature gate.
[#5220](https:/Kong/kubernetes-ingress-controller/pull/5220)
[#5234](https:/Kong/kubernetes-ingress-controller/pull/5234)
[#5282](https:/Kong/kubernetes-ingress-controller/pull/5282)
- Added support for GRPC over HTTP (without TLS) in Gateway API.
[#5128](https:/Kong/kubernetes-ingress-controller/pull/5128)
- Added `-init-cache-sync-duration` CLI flag. This flag configures how long the controller waits for Kubernetes resources to populate at startup before generating the initial Kong configuration. It also fixes a bug that removed the default 5 second wait period.
Expand Down
14 changes: 11 additions & 3 deletions internal/dataplane/translator/ingressrules.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,14 @@ func (ir *ingressRules) populateServices(logger logr.Logger, s store.Storer, fai

// collect all the Kubernetes services configured for the service backends,
// and all annotations with our prefix in use across all services (when applicable).
k8sServices, seenKongAnnotations := getK8sServicesForBackends(logger, s, service.Namespace, service.Backends)
serviceParent := ir.ServiceNameToParent[key]
k8sServices, seenKongAnnotations := getK8sServicesForBackends(
s,
service.Namespace,
service.Backends,
failuresCollector,
serviceParent,
)

// if the Kubernetes services have been deemed invalid, log an error message
// and skip the current service.
Expand Down Expand Up @@ -258,10 +265,11 @@ func (s SNIs) Hosts() []string {
}

func getK8sServicesForBackends(
log logr.Logger,
storer store.Storer,
namespace string,
backends kongstate.ServiceBackends,
failuresCollector *failures.ResourceFailuresCollector,
parent client.Object,
) ([]*corev1.Service, map[string]string) {
// we collect all annotations seen for this group of services so that these
// can be later validated.
Expand All @@ -273,7 +281,7 @@ func getK8sServicesForBackends(
for _, backend := range backends {
k8sService, err := resolveKubernetesServiceForBackend(storer, namespace, backend)
if err != nil {
log.Error(err, "Failed to resolve Kubernetes Service for backend")
failuresCollector.PushResourceFailure(fmt.Sprintf("failed to resolve Kubernetes Service for backend: %s", err), parent)
continue
}
if k8sService != nil {
Expand Down
22 changes: 14 additions & 8 deletions internal/dataplane/translator/ingressrules_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package translator
import (
"testing"

"github.com/go-logr/logr"
"github.com/go-logr/zapr"
"github.com/kong/go-kong/kong"
"github.com/samber/lo"
Expand Down Expand Up @@ -252,7 +253,7 @@ func TestGetK8sServicesForBackends(t *testing.T) {
services []*corev1.Service
expectedServices []*corev1.Service
expectedAnnotations map[string]string
expectedLogEntries []string
expectedFailures []string
}{
{
name: "if all backends have a service then all services will be returned and their annotations recorded",
Expand Down Expand Up @@ -333,24 +334,29 @@ func TestGetK8sServicesForBackends(t *testing.T) {
},
}},
expectedAnnotations: map[string]string{},
expectedLogEntries: []string{
"Failed to resolve Kubernetes Service for backend",
expectedFailures: []string{
"failed to resolve Kubernetes Service for backend: failed to fetch Service default/test-service2: Service default/test-service2 not found",
},
},
} {
t.Run(tt.name, func(t *testing.T) {
parent := &netv1.Ingress{
ObjectMeta: metav1.ObjectMeta{Name: "ingress", Namespace: tt.namespace},
TypeMeta: metav1.TypeMeta{Kind: "Ingress", APIVersion: netv1.SchemeGroupVersion.String()},
}
storer, err := store.NewFakeStore(store.FakeObjects{Services: tt.services})
require.NoError(t, err)

core, logs := observer.New(zap.InfoLevel)
logger := zapr.NewLogger(zap.New(core))
failuresCollector := failures.NewResourceFailuresCollector(logr.Discard())

services, annotations := getK8sServicesForBackends(logger, storer, tt.namespace, tt.backends)
services, annotations := getK8sServicesForBackends(storer, tt.namespace, tt.backends, failuresCollector, parent)
assert.Equal(t, tt.expectedServices, services)
assert.Equal(t, tt.expectedAnnotations, annotations)
for i, expectedLogEntry := range tt.expectedLogEntries {
assert.Contains(t, logs.All()[i].Entry.Message, expectedLogEntry)
var collectedFailures []string
for _, failure := range failuresCollector.PopResourceFailures() {
collectedFailures = append(collectedFailures, failure.Message())
}
assert.Equal(t, tt.expectedFailures, collectedFailures)
})
}
}
Expand Down
5 changes: 3 additions & 2 deletions internal/dataplane/translator/subtranslator/ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ func (i *ingressTranslationIndex) getIngressPathBackend(namespace string, httpIn
}

if resource := httpIngressPath.Backend.Resource; resource != nil {
if !isKongServiceFacade(resource) {
if !IsKongServiceFacade(resource) {
gk := resource.Kind
if resource.APIGroup != nil {
gk = *resource.APIGroup + "/" + gk
Expand All @@ -210,7 +210,8 @@ func (i *ingressTranslationIndex) getIngressPathBackend(namespace string, httpIn
return ingressTranslationMetaBackend{}, fmt.Errorf("no Service or Resource specified for Ingress path")
}

func isKongServiceFacade(resource *corev1.TypedLocalObjectReference) bool {
// IsKongServiceFacade returns true if the given resource reference is a KongServiceFacade.
func IsKongServiceFacade(resource *corev1.TypedLocalObjectReference) bool {
return resource.Kind == incubatorv1alpha1.KongServiceFacadeKind &&
resource.APIGroup != nil && *resource.APIGroup == incubatorv1alpha1.GroupVersion.Group
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ spec:
name: svc-facade-beta
path: /beta
pathType: Exact
defaultBackend:
resource:
apiGroup: incubator.konghq.com
kind: KongServiceFacade
name: svc-facade-default
---
apiVersion: v1
kind: Service
Expand Down Expand Up @@ -92,6 +97,18 @@ spec:
name: svc
port: 80
---
apiVersion: incubator.konghq.com/v1alpha1
kind: KongServiceFacade
metadata:
annotations:
kubernetes.io/ingress.class: kong
name: svc-facade-default
namespace: default
spec:
backendRef:
name: svc
port: 80
---
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
Expand Down
Loading