sigs.k8s.io/external-dns@v0.14.1/source/kong_tcpingress_test.go (about) 1 /* 2 Copyright 2021 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package source 18 19 import ( 20 "context" 21 "encoding/json" 22 "testing" 23 24 "github.com/stretchr/testify/assert" 25 corev1 "k8s.io/api/core/v1" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 28 "k8s.io/apimachinery/pkg/runtime" 29 fakeDynamic "k8s.io/client-go/dynamic/fake" 30 fakeKube "k8s.io/client-go/kubernetes/fake" 31 "sigs.k8s.io/external-dns/endpoint" 32 ) 33 34 // This is a compile-time validation that kongTCPIngressSource is a Source. 35 var _ Source = &kongTCPIngressSource{} 36 37 const defaultKongNamespace = "kong" 38 39 func TestKongTCPIngressEndpoints(t *testing.T) { 40 t.Parallel() 41 42 for _, ti := range []struct { 43 title string 44 tcpProxy TCPIngress 45 ignoreHostnameAnnotation bool 46 expected []*endpoint.Endpoint 47 }{ 48 { 49 title: "TCPIngress with hostname annotation", 50 tcpProxy: TCPIngress{ 51 TypeMeta: metav1.TypeMeta{ 52 APIVersion: kongGroupdVersionResource.GroupVersion().String(), 53 Kind: "TCPIngress", 54 }, 55 ObjectMeta: metav1.ObjectMeta{ 56 Name: "tcp-ingress-annotation", 57 Namespace: defaultKongNamespace, 58 Annotations: map[string]string{ 59 "external-dns.alpha.kubernetes.io/hostname": "a.example.com", 60 "kubernetes.io/ingress.class": "kong", 61 }, 62 }, 63 Spec: tcpIngressSpec{ 64 Rules: []tcpIngressRule{ 65 { 66 Port: 30000, 67 }, 68 { 69 Port: 30001, 70 }, 71 }, 72 }, 73 Status: tcpIngressStatus{ 74 LoadBalancer: corev1.LoadBalancerStatus{ 75 Ingress: []corev1.LoadBalancerIngress{ 76 { 77 Hostname: "a691234567a314e71861a4303f06a3bd-1291189659.us-east-1.elb.amazonaws.com", 78 }, 79 }, 80 }, 81 }, 82 }, 83 expected: []*endpoint.Endpoint{ 84 { 85 DNSName: "a.example.com", 86 Targets: []string{"a691234567a314e71861a4303f06a3bd-1291189659.us-east-1.elb.amazonaws.com"}, 87 RecordType: endpoint.RecordTypeCNAME, 88 RecordTTL: 0, 89 Labels: endpoint.Labels{ 90 "resource": "tcpingress/kong/tcp-ingress-annotation", 91 }, 92 ProviderSpecific: endpoint.ProviderSpecific{}, 93 }, 94 }, 95 }, 96 { 97 title: "TCPIngress using SNI", 98 tcpProxy: TCPIngress{ 99 TypeMeta: metav1.TypeMeta{ 100 APIVersion: kongGroupdVersionResource.GroupVersion().String(), 101 Kind: "TCPIngress", 102 }, 103 ObjectMeta: metav1.ObjectMeta{ 104 Name: "tcp-ingress-sni", 105 Namespace: defaultKongNamespace, 106 Annotations: map[string]string{ 107 "kubernetes.io/ingress.class": "kong", 108 }, 109 }, 110 Spec: tcpIngressSpec{ 111 Rules: []tcpIngressRule{ 112 { 113 Port: 30002, 114 Host: "b.example.com", 115 }, 116 { 117 Port: 30003, 118 Host: "c.example.com", 119 }, 120 }, 121 }, 122 Status: tcpIngressStatus{ 123 LoadBalancer: corev1.LoadBalancerStatus{ 124 Ingress: []corev1.LoadBalancerIngress{ 125 { 126 Hostname: "a123456769a314e71861a4303f06a3bd-1291189659.us-east-1.elb.amazonaws.com", 127 }, 128 }, 129 }, 130 }, 131 }, 132 expected: []*endpoint.Endpoint{ 133 { 134 DNSName: "b.example.com", 135 Targets: []string{"a123456769a314e71861a4303f06a3bd-1291189659.us-east-1.elb.amazonaws.com"}, 136 RecordType: endpoint.RecordTypeCNAME, 137 RecordTTL: 0, 138 Labels: endpoint.Labels{ 139 "resource": "tcpingress/kong/tcp-ingress-sni", 140 }, 141 ProviderSpecific: endpoint.ProviderSpecific{}, 142 }, 143 { 144 DNSName: "c.example.com", 145 Targets: []string{"a123456769a314e71861a4303f06a3bd-1291189659.us-east-1.elb.amazonaws.com"}, 146 RecordType: endpoint.RecordTypeCNAME, 147 Labels: endpoint.Labels{ 148 "resource": "tcpingress/kong/tcp-ingress-sni", 149 }, 150 ProviderSpecific: endpoint.ProviderSpecific{}, 151 }, 152 }, 153 }, 154 { 155 title: "TCPIngress with hostname annotation and using SNI", 156 tcpProxy: TCPIngress{ 157 TypeMeta: metav1.TypeMeta{ 158 APIVersion: kongGroupdVersionResource.GroupVersion().String(), 159 Kind: "TCPIngress", 160 }, 161 ObjectMeta: metav1.ObjectMeta{ 162 Name: "tcp-ingress-both", 163 Namespace: defaultKongNamespace, 164 Annotations: map[string]string{ 165 "external-dns.alpha.kubernetes.io/hostname": "d.example.com", 166 "kubernetes.io/ingress.class": "kong", 167 }, 168 }, 169 Spec: tcpIngressSpec{ 170 Rules: []tcpIngressRule{ 171 { 172 Port: 30004, 173 Host: "e.example.com", 174 }, 175 { 176 Port: 30005, 177 Host: "f.example.com", 178 }, 179 }, 180 }, 181 Status: tcpIngressStatus{ 182 LoadBalancer: corev1.LoadBalancerStatus{ 183 Ingress: []corev1.LoadBalancerIngress{ 184 { 185 Hostname: "a12e71861a4303f063456769a314a3bd-1291189659.us-east-1.elb.amazonaws.com", 186 }, 187 }, 188 }, 189 }, 190 }, 191 expected: []*endpoint.Endpoint{ 192 { 193 DNSName: "d.example.com", 194 Targets: []string{"a12e71861a4303f063456769a314a3bd-1291189659.us-east-1.elb.amazonaws.com"}, 195 RecordType: endpoint.RecordTypeCNAME, 196 RecordTTL: 0, 197 Labels: endpoint.Labels{ 198 "resource": "tcpingress/kong/tcp-ingress-both", 199 }, 200 ProviderSpecific: endpoint.ProviderSpecific{}, 201 }, 202 { 203 DNSName: "e.example.com", 204 Targets: []string{"a12e71861a4303f063456769a314a3bd-1291189659.us-east-1.elb.amazonaws.com"}, 205 RecordType: endpoint.RecordTypeCNAME, 206 RecordTTL: 0, 207 Labels: endpoint.Labels{ 208 "resource": "tcpingress/kong/tcp-ingress-both", 209 }, 210 ProviderSpecific: endpoint.ProviderSpecific{}, 211 }, 212 { 213 DNSName: "f.example.com", 214 Targets: []string{"a12e71861a4303f063456769a314a3bd-1291189659.us-east-1.elb.amazonaws.com"}, 215 RecordType: endpoint.RecordTypeCNAME, 216 RecordTTL: 0, 217 Labels: endpoint.Labels{ 218 "resource": "tcpingress/kong/tcp-ingress-both", 219 }, 220 ProviderSpecific: endpoint.ProviderSpecific{}, 221 }, 222 }, 223 }, 224 { 225 title: "TCPIngress ignoring hostname annotation", 226 tcpProxy: TCPIngress{ 227 TypeMeta: metav1.TypeMeta{ 228 APIVersion: kongGroupdVersionResource.GroupVersion().String(), 229 Kind: "TCPIngress", 230 }, 231 ObjectMeta: metav1.ObjectMeta{ 232 Name: "tcp-ingress-both", 233 Namespace: defaultKongNamespace, 234 Annotations: map[string]string{ 235 "external-dns.alpha.kubernetes.io/hostname": "d.example.com", 236 "kubernetes.io/ingress.class": "kong", 237 }, 238 }, 239 Spec: tcpIngressSpec{ 240 Rules: []tcpIngressRule{ 241 { 242 Port: 30004, 243 Host: "e.example.com", 244 }, 245 { 246 Port: 30005, 247 Host: "f.example.com", 248 }, 249 }, 250 }, 251 Status: tcpIngressStatus{ 252 LoadBalancer: corev1.LoadBalancerStatus{ 253 Ingress: []corev1.LoadBalancerIngress{ 254 { 255 Hostname: "a12e71861a4303f063456769a314a3bd-1291189659.us-east-1.elb.amazonaws.com", 256 }, 257 }, 258 }, 259 }, 260 }, 261 ignoreHostnameAnnotation: true, 262 expected: []*endpoint.Endpoint{ 263 { 264 DNSName: "e.example.com", 265 Targets: []string{"a12e71861a4303f063456769a314a3bd-1291189659.us-east-1.elb.amazonaws.com"}, 266 RecordType: endpoint.RecordTypeCNAME, 267 RecordTTL: 0, 268 Labels: endpoint.Labels{ 269 "resource": "tcpingress/kong/tcp-ingress-both", 270 }, 271 ProviderSpecific: endpoint.ProviderSpecific{}, 272 }, 273 { 274 DNSName: "f.example.com", 275 Targets: []string{"a12e71861a4303f063456769a314a3bd-1291189659.us-east-1.elb.amazonaws.com"}, 276 RecordType: endpoint.RecordTypeCNAME, 277 RecordTTL: 0, 278 Labels: endpoint.Labels{ 279 "resource": "tcpingress/kong/tcp-ingress-both", 280 }, 281 ProviderSpecific: endpoint.ProviderSpecific{}, 282 }, 283 }, 284 }, 285 { 286 title: "TCPIngress with target annotation", 287 tcpProxy: TCPIngress{ 288 TypeMeta: metav1.TypeMeta{ 289 APIVersion: kongGroupdVersionResource.GroupVersion().String(), 290 Kind: "TCPIngress", 291 }, 292 ObjectMeta: metav1.ObjectMeta{ 293 Name: "tcp-ingress-sni", 294 Namespace: defaultKongNamespace, 295 Annotations: map[string]string{ 296 "kubernetes.io/ingress.class": "kong", 297 "external-dns.alpha.kubernetes.io/target": "203.2.45.7", 298 }, 299 }, 300 Spec: tcpIngressSpec{ 301 Rules: []tcpIngressRule{ 302 { 303 Port: 30002, 304 Host: "b.example.com", 305 }, 306 { 307 Port: 30003, 308 Host: "c.example.com", 309 }, 310 }, 311 }, 312 Status: tcpIngressStatus{ 313 LoadBalancer: corev1.LoadBalancerStatus{ 314 Ingress: []corev1.LoadBalancerIngress{ 315 { 316 Hostname: "a123456769a314e71861a4303f06a3bd-1291189659.us-east-1.elb.amazonaws.com", 317 }, 318 }, 319 }, 320 }, 321 }, 322 expected: []*endpoint.Endpoint{ 323 { 324 DNSName: "b.example.com", 325 Targets: []string{"203.2.45.7"}, 326 RecordType: endpoint.RecordTypeA, 327 RecordTTL: 0, 328 Labels: endpoint.Labels{ 329 "resource": "tcpingress/kong/tcp-ingress-sni", 330 }, 331 ProviderSpecific: endpoint.ProviderSpecific{}, 332 }, 333 { 334 DNSName: "c.example.com", 335 Targets: []string{"203.2.45.7"}, 336 RecordType: endpoint.RecordTypeA, 337 Labels: endpoint.Labels{ 338 "resource": "tcpingress/kong/tcp-ingress-sni", 339 }, 340 ProviderSpecific: endpoint.ProviderSpecific{}, 341 }, 342 }, 343 }, 344 } { 345 ti := ti 346 t.Run(ti.title, func(t *testing.T) { 347 t.Parallel() 348 349 fakeKubernetesClient := fakeKube.NewSimpleClientset() 350 scheme := runtime.NewScheme() 351 scheme.AddKnownTypes(kongGroupdVersionResource.GroupVersion(), &TCPIngress{}, &TCPIngressList{}) 352 fakeDynamicClient := fakeDynamic.NewSimpleDynamicClient(scheme) 353 354 tcpi := unstructured.Unstructured{} 355 356 tcpIngressAsJSON, err := json.Marshal(ti.tcpProxy) 357 assert.NoError(t, err) 358 359 assert.NoError(t, tcpi.UnmarshalJSON(tcpIngressAsJSON)) 360 361 // Create proxy resources 362 _, err = fakeDynamicClient.Resource(kongGroupdVersionResource).Namespace(defaultKongNamespace).Create(context.Background(), &tcpi, metav1.CreateOptions{}) 363 assert.NoError(t, err) 364 365 source, err := NewKongTCPIngressSource(context.TODO(), fakeDynamicClient, fakeKubernetesClient, defaultKongNamespace, "kubernetes.io/ingress.class=kong", ti.ignoreHostnameAnnotation) 366 assert.NoError(t, err) 367 assert.NotNil(t, source) 368 369 count := &unstructured.UnstructuredList{} 370 for len(count.Items) < 1 { 371 count, _ = fakeDynamicClient.Resource(kongGroupdVersionResource).Namespace(defaultKongNamespace).List(context.Background(), metav1.ListOptions{}) 372 } 373 374 endpoints, err := source.Endpoints(context.Background()) 375 assert.NoError(t, err) 376 assert.Len(t, endpoints, len(ti.expected)) 377 assert.Equal(t, ti.expected, endpoints) 378 }) 379 } 380 }