Skip to content

Commit e45f992

Browse files
committed
Added support for ingress-level listener port annotations
- Added Ingress level listener port annotations, allowing users to specify a single port to multiplex their http(s) traffic through for an ingress - Fixed default backend determination
1 parent d2712dd commit e45f992

File tree

6 files changed

+177
-15
lines changed

6 files changed

+177
-15
lines changed

pkg/controllers/backend/backend.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ func (c *Controller) getDefaultBackends(ingresses []*networkingv1.Ingress) ([]oc
217217

218218
for _, ingress := range ingresses {
219219
if ingress.Spec.DefaultBackend != nil {
220-
if backend != nil && backend != ingress.Spec.DefaultBackend {
220+
if backend != nil && !util.IsBackendServiceEqual(backend, ingress.Spec.DefaultBackend) {
221221
return nil, fmt.Errorf("conflict in default backend resource, only one is permitted")
222222
}
223223
backend = ingress.Spec.DefaultBackend

pkg/controllers/nodeBackend/nodeBackend.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ func (c *Controller) getDefaultBackends(ingresses []*networkingv1.Ingress) ([]oc
283283

284284
for _, ingress := range ingresses {
285285
if ingress.Spec.DefaultBackend != nil {
286-
if backend != nil && backend != ingress.Spec.DefaultBackend {
286+
if backend != nil && !util.IsBackendServiceEqual(backend, ingress.Spec.DefaultBackend) {
287287
return nil, fmt.Errorf("conflict in default backend resource, only one is permitted")
288288
}
289289
backend = ingress.Spec.DefaultBackend

pkg/controllers/routingpolicy/util.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ package routingpolicy
1111

1212
import (
1313
"fmt"
14+
"github.com/pkg/errors"
1415
"strings"
1516

1617
"github.com/oracle/oci-native-ingress-controller/pkg/util"
@@ -74,17 +75,33 @@ func PathToRoutePolicyCondition(host string, path networkingv1.HTTPIngressPath)
7475

7576
func processRoutingPolicy(ingresses []*networkingv1.Ingress, serviceLister corelisters.ServiceLister, listenerPaths map[string][]*listenerPath, desiredRoutingPolicies sets.String) error {
7677
for _, ingress := range ingresses {
78+
tlsConfiguredHosts := sets.NewString()
79+
for tlsIdx := range ingress.Spec.TLS {
80+
ingressTls := ingress.Spec.TLS[tlsIdx]
81+
for hostIdx := range ingressTls.Hosts {
82+
tlsConfiguredHosts.Insert(ingressTls.Hosts[hostIdx])
83+
}
84+
}
85+
7786
for _, rule := range ingress.Spec.Rules {
87+
host := rule.Host
88+
7889
for _, path := range rule.HTTP.Paths {
7990
serviceName, servicePort, err := util.PathToServiceAndPort(ingress.Namespace, path, serviceLister)
8091
if err != nil {
8192
return err
8293
}
94+
95+
listenerPort, err := util.DetermineListenerPort(ingress, &tlsConfiguredHosts, host, servicePort)
96+
if err != nil {
97+
return errors.Wrap(err, "error determining listener port")
98+
}
99+
100+
listenerName := util.GenerateListenerName(listenerPort)
83101
rulePath := path
84-
listenerName := util.GenerateListenerName(servicePort)
85102
listenerPaths[listenerName] = append(listenerPaths[listenerName], &listenerPath{
86103
IngressName: ingress.Name,
87-
Host: rule.Host,
104+
Host: host,
88105
Path: &rulePath,
89106
BackendSetName: util.GenerateBackendSetName(ingress.Namespace, serviceName, servicePort),
90107
})

pkg/state/ingressstate.go

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ func (s *StateStore) BuildState(ingressClass *networkingv1.IngressClass) error {
111111

112112
for _, ing := range ingressGroup {
113113
hostSecretMap := make(map[string]string)
114+
tlsConfiguredHosts := sets.NewString()
114115
desiredPorts := sets.NewInt32()
115116
// we always expect the default_ingress backendset
116117
desiredBackendSets := sets.NewString(DefaultIngressName)
@@ -119,24 +120,33 @@ func (s *StateStore) BuildState(ingressClass *networkingv1.IngressClass) error {
119120
ingressTls := ing.Spec.TLS[ingressItem]
120121
for j := range ingressTls.Hosts {
121122
host := ingressTls.Hosts[j]
123+
tlsConfiguredHosts.Insert(host)
122124
hostSecretMap[host] = ingressTls.SecretName
123125
}
124126
}
125127

126128
for _, rule := range ing.Spec.Rules {
129+
host := rule.Host
130+
127131
for _, path := range rule.HTTP.Paths {
128132
serviceName, servicePort, err := util.PathToServiceAndPort(ing.Namespace, path, s.ServiceLister)
129133
if err != nil {
130134
return errors.Wrap(err, "error finding service and port")
131135
}
132136

133-
desiredPorts.Insert(servicePort)
134-
allListeners.Insert(servicePort)
137+
listenerPort, err := util.DetermineListenerPort(ing, &tlsConfiguredHosts, host, servicePort)
138+
if err != nil {
139+
return errors.Wrap(err, "error determining listener port")
140+
}
141+
142+
desiredPorts.Insert(listenerPort)
143+
allListeners.Insert(listenerPort)
144+
135145
bsName := util.GenerateBackendSetName(ing.Namespace, serviceName, servicePort)
136146
desiredBackendSets.Insert(bsName)
137147
allBackendSets.Insert(bsName)
138148

139-
err = validateListenerProtocol(ing, listenerProtocolMap, servicePort)
149+
err = validateListenerProtocol(ing, listenerProtocolMap, listenerPort)
140150
if err != nil {
141151
return err
142152
}
@@ -153,9 +163,9 @@ func (s *StateStore) BuildState(ingressClass *networkingv1.IngressClass) error {
153163
bsTLSEnabled := util.GetBackendTlsEnabled(ing)
154164
certificateId := util.GetListenerTlsCertificateOcid(ing)
155165
if certificateId != nil {
156-
tlsPortDetail, ok := listenerTLSConfigMap[servicePort]
166+
tlsPortDetail, ok := listenerTLSConfigMap[listenerPort]
157167
if ok {
158-
err = validatePortInUse(tlsPortDetail, "", certificateId, servicePort)
168+
err = validatePortInUse(tlsPortDetail, "", certificateId, listenerPort)
159169
if err != nil {
160170
return errors.Wrap(err, "validating certificates")
161171
}
@@ -164,17 +174,17 @@ func (s *StateStore) BuildState(ingressClass *networkingv1.IngressClass) error {
164174
Type: ArtifactTypeCertificate,
165175
Artifact: *certificateId,
166176
}
167-
listenerTLSConfigMap[servicePort] = config
177+
listenerTLSConfigMap[listenerPort] = config
168178
updateBackendTlsStatus(bsTLSEnabled, bsTLSConfigMap, bsName, config)
169179
}
170180

171-
if rule.Host != "" {
172-
secretName, ok := hostSecretMap[rule.Host]
181+
if host != "" {
182+
secretName, ok := hostSecretMap[host]
173183

174184
if ok && secretName != "" {
175-
tlsPortDetail, ok := listenerTLSConfigMap[servicePort]
185+
tlsPortDetail, ok := listenerTLSConfigMap[listenerPort]
176186
if ok {
177-
err = validatePortInUse(tlsPortDetail, secretName, nil, servicePort)
187+
err = validatePortInUse(tlsPortDetail, secretName, nil, listenerPort)
178188
if err != nil {
179189
return errors.Wrap(err, "validating secrets")
180190
}
@@ -183,7 +193,7 @@ func (s *StateStore) BuildState(ingressClass *networkingv1.IngressClass) error {
183193
Type: ArtifactTypeSecret,
184194
Artifact: secretName,
185195
}
186-
listenerTLSConfigMap[servicePort] = config
196+
listenerTLSConfigMap[listenerPort] = config
187197
updateBackendTlsStatus(bsTLSEnabled, bsTLSConfigMap, bsName, config)
188198
}
189199
}

pkg/util/util.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"encoding/hex"
1616
"encoding/json"
1717
"fmt"
18+
"k8s.io/apimachinery/pkg/util/sets"
1819
"strconv"
1920
"strings"
2021
"time"
@@ -69,13 +70,16 @@ const (
6970
IngressHealthCheckReturnCodeAnnotation = "oci-native-ingress.oraclecloud.com/healthcheck-return-code"
7071
IngressHealthCheckResponseBodyRegexAnnotation = "oci-native-ingress.oraclecloud.com/healthcheck-response-regex"
7172
IngressHealthCheckForcePlainTextAnnotation = "oci-native-ingress.oraclecloud.com/healthcheck-force-plaintext"
73+
IngressHttpListenerPortAnnotation = "oci-native-ingress.oraclecloud.com/http-listener-port"
74+
IngressHttpsListenerPortAnnotation = "oci-native-ingress.oraclecloud.com/https-listener-port"
7275

7376
ProtocolTCP = "TCP"
7477
ProtocolHTTP = "HTTP"
7578
ProtocolHTTP2 = "HTTP2"
7679
ProtocolHTTP2DefaultCipherSuite = "oci-default-http2-ssl-cipher-suite-v1"
7780
DefaultHealthCheckProtocol = ProtocolTCP
7881
DefaultHealthCheckPort = 0
82+
ZeroPort = 0
7983
DefaultHealthCheckTimeOutMilliSeconds = 3000
8084
DefaultHealthCheckIntervalMilliSeconds = 10000
8185
DefaultHealthCheckRetries = 3
@@ -270,6 +274,24 @@ func GetIngressHealthCheckForcePlainText(i *networkingv1.Ingress) bool {
270274
return result
271275
}
272276

277+
func GetIngressHttpListenerPort(i *networkingv1.Ingress) (int, error) {
278+
value, ok := i.Annotations[IngressHttpListenerPortAnnotation]
279+
if !ok {
280+
return ZeroPort, nil
281+
}
282+
283+
return strconv.Atoi(value)
284+
}
285+
286+
func GetIngressHttpsListenerPort(i *networkingv1.Ingress) (int, error) {
287+
value, ok := i.Annotations[IngressHttpsListenerPortAnnotation]
288+
if !ok {
289+
return ZeroPort, nil
290+
}
291+
292+
return strconv.Atoi(value)
293+
}
294+
273295
func PathToRoutePolicyName(ingressName string, host string, path networkingv1.HTTPIngressPath) string {
274296
h := sha256.New()
275297
h.Write([]byte(ingressName))
@@ -618,3 +640,38 @@ func RetrievePods(endpointLister corelisters.EndpointsLister, podLister corelist
618640
}
619641
return pods, nil
620642
}
643+
644+
func DetermineListenerPort(ingress *networkingv1.Ingress, tlsConfiguredHosts *sets.String, host string, servicePort int32) (int32, error) {
645+
annotatedHttpPort, err := GetIngressHttpListenerPort(ingress)
646+
if err != nil {
647+
return 0, fmt.Errorf("error parsing Ingress Http Listener Port: %w", err)
648+
}
649+
annotatedHttpsPort, err := GetIngressHttpsListenerPort(ingress)
650+
if err != nil {
651+
return 0, fmt.Errorf("error parsing Ingress Https Listener Port: %w", err)
652+
}
653+
654+
isCertOcidPresent := GetListenerTlsCertificateOcid(ingress) != nil
655+
656+
listenerPort := servicePort
657+
if isCertOcidPresent || tlsConfiguredHosts.Has(host) {
658+
if annotatedHttpsPort != ZeroPort {
659+
listenerPort = int32(annotatedHttpsPort)
660+
}
661+
} else if annotatedHttpPort != ZeroPort {
662+
listenerPort = int32(annotatedHttpPort)
663+
}
664+
665+
return listenerPort, nil
666+
}
667+
668+
// b1 and b2 are assumed non-nil
669+
func IsBackendServiceEqual(b1 *networkingv1.IngressBackend, b2 *networkingv1.IngressBackend) bool {
670+
if b1.Service == b2.Service {
671+
return true
672+
}
673+
if b1.Service == nil || b2.Service == nil || *b1.Service != *b2.Service {
674+
return false
675+
}
676+
return true
677+
}

pkg/util/util_test.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ package util
1111
import (
1212
"context"
1313
"fmt"
14+
"k8s.io/apimachinery/pkg/util/sets"
1415
"strconv"
1516
"strings"
1617
"testing"
@@ -666,3 +667,80 @@ func TestGetTimeDifferenceInSeconds(t *testing.T) {
666667
Expect(GetTimeDifferenceInSeconds(1257894006000, 1257894009000)).Should(Equal(float64(3)))
667668
Expect(GetTimeDifferenceInSeconds(1257894006000, 1257894009600)).Should(Equal(3.6))
668669
}
670+
671+
func TestDetermineListenerPort(t *testing.T) {
672+
RegisterTestingT(t)
673+
servicePort := int32(8080)
674+
httpPort := int32(80)
675+
httpsPort := int32(443)
676+
tlsConfiguredHosts := sets.NewString("tls-configured-1", "tls-configured-2")
677+
ingress := &networkingv1.Ingress{}
678+
annotations := map[string]string{}
679+
ingress.Annotations = annotations
680+
681+
listenerPort, err := DetermineListenerPort(ingress, &tlsConfiguredHosts, "not-tls-configured", servicePort)
682+
Expect(err).NotTo(HaveOccurred())
683+
Expect(listenerPort).Should(Equal(servicePort))
684+
685+
annotations[IngressHttpListenerPortAnnotation] = "80"
686+
listenerPort, err = DetermineListenerPort(ingress, &tlsConfiguredHosts, "not-tls-configured", servicePort)
687+
Expect(err).NotTo(HaveOccurred())
688+
Expect(listenerPort).Should(Equal(httpPort))
689+
690+
listenerPort, err = DetermineListenerPort(ingress, &tlsConfiguredHosts, "tls-configured-1", servicePort)
691+
Expect(err).NotTo(HaveOccurred())
692+
Expect(listenerPort).Should(Equal(servicePort))
693+
694+
annotations[IngressHttpsListenerPortAnnotation] = "443"
695+
listenerPort, err = DetermineListenerPort(ingress, &tlsConfiguredHosts, "tls-configured-1", servicePort)
696+
Expect(err).NotTo(HaveOccurred())
697+
Expect(listenerPort).Should(Equal(httpsPort))
698+
699+
delete(annotations, IngressHttpsListenerPortAnnotation)
700+
annotations[IngressListenerTlsCertificateAnnotation] = "oci_cert"
701+
listenerPort, err = DetermineListenerPort(ingress, &tlsConfiguredHosts, "not-tls-configured", servicePort)
702+
Expect(err).NotTo(HaveOccurred())
703+
Expect(listenerPort).Should(Equal(servicePort))
704+
705+
annotations[IngressHttpsListenerPortAnnotation] = "443"
706+
listenerPort, err = DetermineListenerPort(ingress, &tlsConfiguredHosts, "not-tls-configured", servicePort)
707+
Expect(err).NotTo(HaveOccurred())
708+
Expect(listenerPort).Should(Equal(httpsPort))
709+
}
710+
711+
func TestIsBackendServiceEqual(t *testing.T) {
712+
RegisterTestingT(t)
713+
b1 := &networkingv1.IngressBackend{}
714+
b2 := &networkingv1.IngressBackend{
715+
Service: &networkingv1.IngressServiceBackend{
716+
Name: "default-backend-1",
717+
Port: networkingv1.ServiceBackendPort{
718+
Number: 80,
719+
},
720+
},
721+
}
722+
b3 := &networkingv1.IngressBackend{
723+
Service: &networkingv1.IngressServiceBackend{
724+
Name: "default-backend-1",
725+
Port: networkingv1.ServiceBackendPort{
726+
Number: 80,
727+
},
728+
},
729+
}
730+
b4 := &networkingv1.IngressBackend{
731+
Service: &networkingv1.IngressServiceBackend{
732+
Name: "default-backend-2",
733+
Port: networkingv1.ServiceBackendPort{
734+
Number: 80,
735+
},
736+
},
737+
}
738+
739+
Expect(IsBackendServiceEqual(b2, b3)).To(BeTrue())
740+
741+
Expect(IsBackendServiceEqual(b1, b2)).To(BeFalse())
742+
Expect(IsBackendServiceEqual(b1, b3)).To(BeFalse())
743+
Expect(IsBackendServiceEqual(b1, b4)).To(BeFalse())
744+
Expect(IsBackendServiceEqual(b2, b4)).To(BeFalse())
745+
Expect(IsBackendServiceEqual(b3, b4)).To(BeFalse())
746+
}

0 commit comments

Comments
 (0)