Skip to content

Commit

Permalink
feat: resolve dependencies for UDPIngress and TCPIngress (#6066)
Browse files Browse the repository at this point in the history
  • Loading branch information
programmer04 committed May 23, 2024
1 parent eb04ce9 commit 6f17a07
Show file tree
Hide file tree
Showing 3 changed files with 274 additions and 8 deletions.
36 changes: 30 additions & 6 deletions internal/dataplane/fallback/graph_dependencies_kong.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package fallback

import (
"fmt"

k8stypes "k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"

Expand Down Expand Up @@ -82,14 +84,36 @@ func resolveKongConsumerGroupDependencies(cache store.CacheStores, kongConsumerG
return resolveObjectDependenciesPlugin(cache, kongConsumerGroup)
}

// TODO: https://github.com/Kong/kubernetes-ingress-controller/issues/5929
func resolveUDPIngressDependencies(_ store.CacheStores, _ *kongv1beta1.UDPIngress) []client.Object {
return nil
// resolveUDPIngressDependencies resolves potential dependencies for a UDPIngress object:
// - KongPlugin
// - KongClusterPlugin
// - Service.
func resolveUDPIngressDependencies(cache store.CacheStores, udpIngress *kongv1beta1.UDPIngress) []client.Object {
dependencies := resolveObjectDependenciesPlugin(cache, udpIngress)
for _, rule := range udpIngress.Spec.Rules {
if service, exists, err := cache.Service.GetByKey(
fmt.Sprintf("%s/%s", udpIngress.GetNamespace(), rule.Backend.ServiceName),
); err == nil && exists {
dependencies = append(dependencies, service.(client.Object))
}
}
return dependencies
}

// TODO: https://github.com/Kong/kubernetes-ingress-controller/issues/5929
func resolveTCPIngressDependencies(_ store.CacheStores, _ *kongv1beta1.TCPIngress) []client.Object {
return nil
// resolveTCPIngressDependencies resolves potential dependencies for a TCPIngress object:
// - KongPlugin
// - KongClusterPlugin
// - Service.
func resolveTCPIngressDependencies(cache store.CacheStores, tcpIngress *kongv1beta1.TCPIngress) []client.Object {
dependencies := resolveObjectDependenciesPlugin(cache, tcpIngress)
for _, rule := range tcpIngress.Spec.Rules {
if service, exists, err := cache.Service.GetByKey(
fmt.Sprintf("%s/%s", tcpIngress.GetNamespace(), rule.Backend.ServiceName),
); err == nil && exists {
dependencies = append(dependencies, service.(client.Object))
}
}
return dependencies
}

// resolveKongServiceFacadeDependencies resolves potential dependencies for a KongServiceFacade object:
Expand Down
238 changes: 238 additions & 0 deletions internal/dataplane/fallback/graph_dependencies_kong_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -468,3 +468,241 @@ func TestResolveDependencies_KongServiceFacade(t *testing.T) {
runResolveDependenciesTest(t, tc)
}
}

func TestResolveDependencies_UDPIngress(t *testing.T) {
testCases := []resolveDependenciesTestCase{
{
name: "no dependencies",
object: &kongv1beta1.UDPIngress{
ObjectMeta: metav1.ObjectMeta{
Name: "test-UDPIngress",
Namespace: "test-namespace",
},
},
cache: cacheStoresFromObjs(t,
testKongPlugin(t, "1"),
testKongClusterPlugin(t, "1"),
),
expected: []client.Object{},
},
{
name: "UDPIngress -> plugins - annotation (KongPlugin and KongClusterPlugin with the same name) and referenced Service",
object: &kongv1beta1.UDPIngress{
ObjectMeta: metav1.ObjectMeta{
Name: "test-UDPIngress",
Namespace: "test-namespace",
Annotations: map[string]string{
annotations.AnnotationPrefix + annotations.PluginsKey: "1, 2",
},
},
Spec: kongv1beta1.UDPIngressSpec{
Rules: []kongv1beta1.UDPIngressRule{
{
Backend: kongv1beta1.IngressBackend{
ServiceName: "1",
},
},
},
},
},
cache: cacheStoresFromObjs(t,
testKongPlugin(t, "1"),
testKongPlugin(t, "2"),
testService(t, "1"),
testKongClusterPlugin(t, "1"),
),
expected: []client.Object{testKongPlugin(t, "1"), testKongPlugin(t, "2"), testService(t, "1")},
},
{
name: "UDPIngress -> plugins - annotation (KongPlugin and KongClusterPlugin with different names) and duplicated Service in different namespaces",
object: &kongv1beta1.UDPIngress{
ObjectMeta: metav1.ObjectMeta{
Name: "test-UDPIngress",
Namespace: "test-namespace",
Annotations: map[string]string{
annotations.AnnotationPrefix + annotations.PluginsKey: "1, 3",
},
},
Spec: kongv1beta1.UDPIngressSpec{
Rules: []kongv1beta1.UDPIngressRule{
{
Backend: kongv1beta1.IngressBackend{
ServiceName: "1",
},
},
},
},
},
cache: cacheStoresFromObjs(t,
testKongPlugin(t, "1"),
testKongPlugin(t, "2"),
testKongClusterPlugin(t, "3"),
testService(t, "1"),
testService(t, "1", func(s *corev1.Service) {
s.Namespace = "other-namespace"
}),
),
expected: []client.Object{testKongPlugin(t, "1"), testKongClusterPlugin(t, "3"), testService(t, "1")},
},
{
name: "UDPIngress -> plugins - annotation (KongClusterPlugin) and referenced Services",
object: &kongv1beta1.UDPIngress{
ObjectMeta: metav1.ObjectMeta{
Name: "test-UDPIngress",
Namespace: "test-namespace",
Annotations: map[string]string{
annotations.AnnotationPrefix + annotations.PluginsKey: "3",
kongv1beta1.KongUpstreamPolicyAnnotationKey: "3",
},
},
Spec: kongv1beta1.UDPIngressSpec{
Rules: []kongv1beta1.UDPIngressRule{
{
Backend: kongv1beta1.IngressBackend{
ServiceName: "1",
},
},
{
Backend: kongv1beta1.IngressBackend{
ServiceName: "2",
},
},
},
},
},
cache: cacheStoresFromObjs(t,
testKongPlugin(t, "1"),
testKongPlugin(t, "2"),
testKongClusterPlugin(t, "3"),
testKongServiceFacade(t, "1"),
testKongServiceFacade(t, "2"),
testService(t, "1"),
testService(t, "2"),
),
expected: []client.Object{testKongClusterPlugin(t, "3"), testService(t, "1"), testService(t, "2")},
},
}

for _, tc := range testCases {
runResolveDependenciesTest(t, tc)
}
}

func TestResolveDependencies_TCPIngress(t *testing.T) {
testCases := []resolveDependenciesTestCase{
{
name: "no dependencies",
object: &kongv1beta1.TCPIngress{
ObjectMeta: metav1.ObjectMeta{
Name: "test-TCPIngress",
Namespace: "test-namespace",
},
},
cache: cacheStoresFromObjs(t,
testKongPlugin(t, "1"),
testKongClusterPlugin(t, "1"),
),
expected: []client.Object{},
},
{
name: "TCPIngress -> plugins - annotation (KongPlugin and KongClusterPlugin with the same name) and referenced Service",
object: &kongv1beta1.TCPIngress{
ObjectMeta: metav1.ObjectMeta{
Name: "test-TCPIngress",
Namespace: "test-namespace",
Annotations: map[string]string{
annotations.AnnotationPrefix + annotations.PluginsKey: "1, 2",
},
},
Spec: kongv1beta1.TCPIngressSpec{
Rules: []kongv1beta1.IngressRule{
{
Backend: kongv1beta1.IngressBackend{
ServiceName: "1",
},
},
},
},
},
cache: cacheStoresFromObjs(t,
testKongPlugin(t, "1"),
testKongPlugin(t, "2"),
testService(t, "1"),
testKongClusterPlugin(t, "1"),
),
expected: []client.Object{testKongPlugin(t, "1"), testKongPlugin(t, "2"), testService(t, "1")},
},
{
name: "TCPIngress -> plugins - annotation (KongPlugin and KongClusterPlugin with different names) and duplicated Service in different namespaces",
object: &kongv1beta1.TCPIngress{
ObjectMeta: metav1.ObjectMeta{
Name: "test-TCPIngress",
Namespace: "test-namespace",
Annotations: map[string]string{
annotations.AnnotationPrefix + annotations.PluginsKey: "1, 3",
},
},
Spec: kongv1beta1.TCPIngressSpec{
Rules: []kongv1beta1.IngressRule{
{
Backend: kongv1beta1.IngressBackend{
ServiceName: "1",
},
},
},
},
},
cache: cacheStoresFromObjs(t,
testKongPlugin(t, "1"),
testKongPlugin(t, "2"),
testKongClusterPlugin(t, "3"),
testService(t, "1"),
testService(t, "1", func(s *corev1.Service) {
s.Namespace = "other-namespace"
}),
),
expected: []client.Object{testKongPlugin(t, "1"), testKongClusterPlugin(t, "3"), testService(t, "1")},
},
{
name: "TCPIngress -> plugins - annotation (KongClusterPlugin) and referenced Services",
object: &kongv1beta1.TCPIngress{
ObjectMeta: metav1.ObjectMeta{
Name: "test-TCPIngress",
Namespace: "test-namespace",
Annotations: map[string]string{
annotations.AnnotationPrefix + annotations.PluginsKey: "3",
kongv1beta1.KongUpstreamPolicyAnnotationKey: "3",
},
},
Spec: kongv1beta1.TCPIngressSpec{
Rules: []kongv1beta1.IngressRule{
{
Backend: kongv1beta1.IngressBackend{
ServiceName: "1",
},
},
{
Backend: kongv1beta1.IngressBackend{
ServiceName: "2",
},
},
},
},
},
cache: cacheStoresFromObjs(t,
testKongPlugin(t, "1"),
testKongPlugin(t, "2"),
testKongClusterPlugin(t, "3"),
testKongServiceFacade(t, "1"),
testKongServiceFacade(t, "2"),
testService(t, "1"),
testService(t, "2"),
),
expected: []client.Object{testKongClusterPlugin(t, "3"), testService(t, "1"), testService(t, "2")},
},
}

for _, tc := range testCases {
runResolveDependenciesTest(t, tc)
}
}
8 changes: 6 additions & 2 deletions internal/dataplane/fallback/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,17 @@ func testIngressClass(t *testing.T, name string) *netv1.IngressClass {
})
}

func testService(t *testing.T, name string) *corev1.Service {
return helpers.WithTypeMeta(t, &corev1.Service{
func testService(t *testing.T, name string, modifiers ...func(s *corev1.Service)) *corev1.Service {
svc := helpers.WithTypeMeta(t, &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: testNamespace,
},
})
for _, mod := range modifiers {
mod(svc)
}
return svc
}

func testSecret(t *testing.T, name string, modifiers ...func(s *corev1.Secret)) *corev1.Secret {
Expand Down

0 comments on commit 6f17a07

Please sign in to comment.