Skip to content

Commit e26b8ee

Browse files
allow same port to used on both public and private ingresses (#1539)
1 parent 273d638 commit e26b8ee

File tree

6 files changed

+166
-34
lines changed

6 files changed

+166
-34
lines changed

pkg/appgw/configbuilder.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,8 +254,8 @@ func generateListenerID(ingress *networking.Ingress, rule *networking.IngressRul
254254
}
255255

256256
extendedHostNames, err := annotations.GetHostNameExtensions(ingress)
257-
if err != nil {
258-
klog.V(5).Infof("Error while parsing hostname extension: %s", err)
257+
if err != nil && !controllererrors.IsErrorCode(err, controllererrors.ErrorMissingAnnotation) {
258+
klog.V(5).Infof("Error while parsing host name extensions: %s", err)
259259
} else {
260260
if extendedHostNames != nil {
261261
hostNames = append(hostNames, extendedHostNames...)

pkg/appgw/frontend_listeners.go

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ func (c *appGwConfigBuilder) getListeners(cbCtx *ConfigBuilderContext) (*[]n.App
2323
return c.mem.listeners, c.mem.ports
2424
}
2525

26-
publIPPorts := make(map[string]string)
2726
portsByNumber := cbCtx.ExistingPortsByNumber
2827
var listeners []n.ApplicationGatewayHTTPListener
2928

@@ -32,7 +31,7 @@ func (c *appGwConfigBuilder) getListeners(cbCtx *ConfigBuilderContext) (*[]n.App
3231
}
3332

3433
if cbCtx.EnvVariables.EnableIstioIntegration {
35-
listeners, portsByNumber, publIPPorts = c.getIstioListenersPorts(cbCtx)
34+
listeners, portsByNumber = c.getIstioListenersPorts(cbCtx)
3635
}
3736

3837
for listenerID, config := range c.getListenerConfigs(cbCtx) {
@@ -42,15 +41,6 @@ func (c *appGwConfigBuilder) getListeners(cbCtx *ConfigBuilderContext) (*[]n.App
4241
continue
4342
}
4443

45-
if listenerName, exists := publIPPorts[*port.Name]; exists && listenerID.FrontendType == FrontendTypePrivate {
46-
klog.Errorf("Can't assign port %s to Private IP Listener %s; already assigned to Public IP Listener %s; Will not create listener %+v", *port.Name, *listener.Name, listenerName, listenerID)
47-
continue
48-
}
49-
50-
if listenerID.FrontendType == FrontendTypePublic {
51-
publIPPorts[*port.Name] = *listener.Name
52-
}
53-
5444
// newlistener created a new port; Add it to the set
5545
if _, exists := portsByNumber[Port(*port.Port)]; !exists {
5646
portsByNumber[Port(*port.Port)] = *port
@@ -64,6 +54,7 @@ func (c *appGwConfigBuilder) getListeners(cbCtx *ConfigBuilderContext) (*[]n.App
6454
listener.SslProfile = resourceRef(sslProfileID)
6555
}
6656
}
57+
6758
if config.FirewallPolicy != "" {
6859
listener.FirewallPolicy = &n.SubResource{ID: to.StringPtr(config.FirewallPolicy)}
6960
}

pkg/appgw/frontend_listeners_istio.go

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ import (
1010
"k8s.io/klog/v2"
1111
)
1212

13-
func (c *appGwConfigBuilder) getIstioListenersPorts(cbCtx *ConfigBuilderContext) ([]n.ApplicationGatewayHTTPListener, map[Port]n.ApplicationGatewayFrontendPort, map[string]string) {
14-
publIPPorts := make(map[string]string)
13+
func (c *appGwConfigBuilder) getIstioListenersPorts(cbCtx *ConfigBuilderContext) ([]n.ApplicationGatewayHTTPListener, map[Port]n.ApplicationGatewayFrontendPort) {
1514
portsByNumber := cbCtx.ExistingPortsByNumber
1615
var listeners []n.ApplicationGatewayHTTPListener
1716

@@ -22,20 +21,12 @@ func (c *appGwConfigBuilder) getIstioListenersPorts(cbCtx *ConfigBuilderContext)
2221
klog.Errorf("Failed creating listener %+v: %s", listenerID, err)
2322
continue
2423
}
25-
if listenerName, exists := publIPPorts[*port.Name]; exists && listenerID.FrontendType == FrontendTypePrivate {
26-
klog.Errorf("Can't assign port %s to Private IP Listener %s; already assigned to Public IP Listener %s", *port.Name, *listener.Name, listenerName)
27-
continue
28-
}
29-
30-
if listenerID.FrontendType == FrontendTypePublic {
31-
publIPPorts[*port.Name] = *listener.Name
32-
}
3324

3425
listeners = append(listeners, *listener)
3526
if _, exists := portsByNumber[Port(*port.Port)]; !exists {
3627
portsByNumber[Port(*port.Port)] = *port
3728
}
3829
}
3930
}
40-
return listeners, portsByNumber, publIPPorts
31+
return listeners, portsByNumber
4132
}

scripts/e2e/cmd/runner/helper.go

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -696,16 +696,23 @@ func getPublicIPForNetworkingV1Ingress(clientset *clientset.Clientset, namespace
696696
return "", fmt.Errorf("Unable to find ingress in namespace %s", namespaceName)
697697
}
698698

699-
ingress := (*ingresses).Items[0]
700-
if len(ingress.Status.LoadBalancer.Ingress) == 0 {
701-
klog.Warning("Trying again in 5 seconds...", i)
702-
time.Sleep(5 * time.Second)
703-
continue
704-
}
699+
for _, ingress := range (*ingresses).Items {
700+
if ingress.Annotations["appgw.ingress.kubernetes.io/use-private-ip"] == "true" {
701+
continue
702+
}
705703

706-
publicIP := ingress.Status.LoadBalancer.Ingress[0].IP
707-
if publicIP != "" {
708-
return publicIP, nil
704+
if len(ingress.Status.LoadBalancer.Ingress) == 0 {
705+
klog.Warning("Trying again in 5 seconds...", i)
706+
time.Sleep(5 * time.Second)
707+
continue
708+
}
709+
710+
publicIP := ingress.Status.LoadBalancer.Ingress[0].IP
711+
if publicIP != "" {
712+
return publicIP, nil
713+
}
714+
715+
break
709716
}
710717

711718
klog.Warning("getPublicIP: trying again in 5 seconds...", i)

scripts/e2e/cmd/runner/networking-v1-mfu_one_namespace_many_ingresses_test.go

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ package runner
1010

1111
import (
1212
"context"
13+
"encoding/json"
1314
"fmt"
1415
"strconv"
1516
"time"
@@ -18,6 +19,7 @@ import (
1819
. "github.com/onsi/gomega"
1920

2021
versioned "github.com/Azure/application-gateway-kubernetes-ingress/pkg/crd_client/agic_crd_client/clientset/versioned"
22+
n "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2021-03-01/network"
2123
v1 "k8s.io/api/core/v1"
2224
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2325
"k8s.io/client-go/kubernetes"
@@ -221,10 +223,64 @@ var _ = Describe("networking-v1-MFU", func() {
221223
Expect(err).To(BeNil())
222224
})
223225

226+
It("[same-port-public-private] ingresses with same port on both public and private IP should work", func() {
227+
// create namespace
228+
namespaceName = "e2e-same-port-public-private"
229+
ns := &v1.Namespace{
230+
ObjectMeta: metav1.ObjectMeta{
231+
Name: namespaceName,
232+
},
233+
}
234+
klog.Info("Creating namespace: ", namespaceName)
235+
_, err = clientset.CoreV1().Namespaces().Create(context.TODO(), ns, metav1.CreateOptions{})
236+
Expect(err).To(BeNil())
237+
238+
// create objects in the yaml
239+
path := "testdata/networking-v1/one-namespace-many-ingresses/same-port-public-private/app.yaml"
240+
klog.Info("Applying yaml: ", path)
241+
err = applyYaml(clientset, crdClient, namespaceName, path)
242+
Expect(err).To(BeNil())
243+
244+
var exampleComListeners []n.ApplicationGatewayHTTPListener
245+
// Check that gateway has two listeners eventually
246+
klog.Info("Checking that gateway has two listeners for hostname example.com...")
247+
Eventually(func() bool {
248+
appGW, err := getGateway()
249+
Expect(err).To(BeNil())
250+
251+
bytes, _ := json.MarshalIndent(appGW.HTTPListeners, "", " ")
252+
klog.Infof("Listeners: %s", bytes)
253+
254+
exampleComListeners = []n.ApplicationGatewayHTTPListener{}
255+
for _, listener := range *appGW.HTTPListeners {
256+
if listener.HostNames == nil {
257+
continue
258+
}
259+
260+
if len(*listener.HostNames) == 0 {
261+
continue
262+
}
263+
264+
if (*listener.HostNames)[0] == "example.com" {
265+
exampleComListeners = append(exampleComListeners, listener)
266+
}
267+
}
268+
269+
return len(exampleComListeners) == 2
270+
}, 60*time.Second, 5*time.Second).Should(BeTrue())
271+
272+
// Check that both listeners have the same frontend port
273+
klog.Info("Checking that both listeners have the same frontend port...")
274+
Expect(exampleComListeners[0].FrontendPort.ID).To(Equal(exampleComListeners[1].FrontendPort.ID))
275+
276+
// Check that both listeners have the different frontend IP
277+
klog.Info("Checking that both listeners have the different frontend IP...")
278+
Expect(exampleComListeners[0].FrontendIPConfiguration.ID).ToNot(Equal(exampleComListeners[1].FrontendIPConfiguration.ID))
279+
})
280+
224281
AfterEach(func() {
225282
// clear all namespaces
226283
cleanUp(clientset)
227284
})
228285
})
229-
230286
})
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
apiVersion: networking.k8s.io/v1
2+
kind: Ingress
3+
metadata:
4+
name: ing-public
5+
spec:
6+
ingressClassName: azure-application-gateway
7+
rules:
8+
- host: example.com
9+
http:
10+
paths:
11+
- backend:
12+
service:
13+
name: svc
14+
port:
15+
name: pp
16+
path: /public
17+
pathType: Prefix
18+
---
19+
apiVersion: networking.k8s.io/v1
20+
kind: Ingress
21+
metadata:
22+
name: ing1-private
23+
annotations:
24+
appgw.ingress.kubernetes.io/use-private-ip: "true"
25+
spec:
26+
ingressClassName: azure-application-gateway
27+
rules:
28+
- host: example.com
29+
http:
30+
paths:
31+
- backend:
32+
service:
33+
name: svc
34+
port:
35+
name: pp
36+
path: /private
37+
pathType: Prefix
38+
---
39+
apiVersion: v1
40+
kind: Service
41+
metadata:
42+
name: svc
43+
spec:
44+
selector:
45+
app: app
46+
ports:
47+
- name: pp
48+
protocol: TCP
49+
port: 80
50+
targetPort: port
51+
---
52+
apiVersion: apps/v1
53+
kind: Deployment
54+
metadata:
55+
name: depl
56+
spec:
57+
selector:
58+
matchLabels:
59+
app: app
60+
replicas: 1
61+
template:
62+
metadata:
63+
labels:
64+
app: app
65+
spec:
66+
containers:
67+
- name: ctr
68+
imagePullPolicy: Always
69+
image: docker.io/kennethreitz/httpbin
70+
ports:
71+
- name: port
72+
containerPort: 80
73+
livenessProbe:
74+
httpGet:
75+
path: /status/200
76+
port: 80
77+
initialDelaySeconds: 3
78+
periodSeconds: 3
79+
resources:
80+
requests:
81+
cpu: 250m
82+
memory: 64Mi
83+
limits:
84+
cpu: 500m
85+
memory: 128Mi
86+
imagePullSecrets:
87+
- name: acr-creds

0 commit comments

Comments
 (0)