@@ -6,8 +6,11 @@ import (
66
77 . "github.com/onsi/ginkgo/v2"
88 . "github.com/onsi/gomega"
9+ stackitmocks "github.com/stackitcloud/cloud-provider-stackit/pkg/stackit"
910 stackitconfig "github.com/stackitcloud/cloud-provider-stackit/pkg/stackit/config"
1011 albsdk "github.com/stackitcloud/stackit-sdk-go/services/alb/v2api"
12+ certsdk "github.com/stackitcloud/stackit-sdk-go/services/certificates/v2api"
13+ "go.uber.org/mock/gomock"
1114 corev1 "k8s.io/api/core/v1"
1215 networkingv1 "k8s.io/api/networking/v1"
1316 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -18,7 +21,9 @@ import (
1821
1922var _ = Describe ("Node Controller" , func () {
2023 var (
21- k8sClient client.Client
24+ k8sClient client.Client
25+ mockCtrl * gomock.Controller
26+ certClient * stackitmocks.MockCertificatesClient
2227
2328 ingressClass networkingv1.IngressClass
2429 ingress networkingv1.Ingress
@@ -34,7 +39,7 @@ var _ = Describe("Node Controller", func() {
3439 networkID := "my-network"
3540
3641 ingressClass = networkingv1.IngressClass {
37- ObjectMeta : metav1.ObjectMeta {Name : "test-ingress-class" },
42+ ObjectMeta : metav1.ObjectMeta {Name : "test-ingress-class" , UID : "test-ingress-class-uid" },
3843 Spec : networkingv1.IngressClassSpec {Controller : controllerName },
3944 }
4045
@@ -82,6 +87,7 @@ var _ = Describe("Node Controller", func() {
8287
8388 albSpec = albsdk.CreateLoadBalancerPayload {
8489 DisableTargetSecurityGroupAssignment : new (true ),
90+ Labels : new (map [string ]string {LabelIngressClassUID : "test-ingress-class-uid" }),
8591 Listeners : []albsdk.Listener {
8692 {
8793 Http : new (albsdk.ProtocolOptionsHTTP {
@@ -145,14 +151,84 @@ var _ = Describe("Node Controller", func() {
145151 It ("should work with labels" , func () {
146152
147153 reconciler .ALBConfig .ApplicationLoadBalancer .ExtraLabels = map [string ]string {"managed-by" : "alb-ingressClass" }
154+ // adding extra labels to albSpec.Labels map
155+ for k , v := range reconciler .ALBConfig .ApplicationLoadBalancer .ExtraLabels {
156+ (* albSpec .Labels )[k ] = v
157+ }
148158 spec , errorEventList , err := reconciler .getAlbSpecForIngressClass (context .Background (), & ingressClass )
149159 Expect (err ).To (Succeed ())
150160 Expect (errorEventList ).To (BeEmpty ())
151161
152- albSpec .Labels = new (map [string ]string {"managed-by" : "alb-ingressClass" })
162+ Expect (spec ).ToNot (BeNil ())
163+ Expect (* spec ).To (BeEquivalentTo (albSpec ))
164+ })
165+
166+ It ("should work with certificates" , func () {
167+
168+ mockCtrl = gomock .NewController (GinkgoT ())
169+ certClient = stackitmocks .NewMockCertificatesClient (mockCtrl )
170+
171+ // Bind this mock instance to live reconciler reference context
172+ reconciler .CertificateClient = certClient
173+
174+ certSecret := corev1.Secret {
175+ ObjectMeta : metav1.ObjectMeta {
176+ Name : "my-secret-cert" ,
177+ UID : "dummy-secret-uid-value-1234567" ,
178+ },
179+ Type : corev1 .SecretTypeTLS ,
180+ Data : map [string ][]byte {
181+ "tls.crt" : []byte ("mock-public-key" ),
182+ "tls.key" : []byte ("mock-private-key" ),
183+ },
184+ }
185+ Expect (k8sClient .Create (context .Background (), & certSecret )).To (Succeed ())
186+
187+ actualStoredSecret := & corev1.Secret {}
188+ err := k8sClient .Get (context .Background (), client.ObjectKey {Name : "my-secret-cert" }, actualStoredSecret )
189+ Expect (err ).NotTo (HaveOccurred ())
190+
191+ expectedGeneratedCertName := getCertName (& ingressClass , actualStoredSecret )
192+ targetCertID := "real-certificate-uuid-abc-123"
193+
194+ mockResponse := & certsdk.GetCertificateResponse {
195+ Id : new (targetCertID ),
196+ Name : new (expectedGeneratedCertName ),
197+ }
198+
199+ certClient .EXPECT ().
200+ CreateCertificate (
201+ gomock .Any (),
202+ "test-project" ,
203+ "test-region" ,
204+ gomock .Any (), // Intercepts any incoming *certsdk.CreateCertificatePayload matching
205+ ).
206+ Return (mockResponse , nil ).
207+ Times (1 )
208+
209+ httpsIngress := testHttpsIngress (& ingressClass , & service )
210+ httpsIngress .Annotations = map [string ]string {"alb.stackit.cloud/https-only" : "true" }
211+
212+ Expect (k8sClient .Create (context .Background (), new (httpsIngress ))).To (Succeed ())
213+
214+ // expected albSpec should include new https listener
215+ httpListener := testHttpListener (service .Spec .Ports [0 ].NodePort )
216+ httpsListener := testHttpsListener (service .Spec .Ports [0 ].NodePort , targetCertID )
217+ albSpec .Listeners = []albsdk.Listener {
218+ httpsListener ,
219+ httpListener ,
220+ }
221+
222+ // get the specs and compare
223+ spec , errorEventList , err := reconciler .getAlbSpecForIngressClass (context .Background (), & ingressClass )
224+ Expect (err ).To (Succeed ())
225+ Expect (errorEventList ).To (BeEmpty ())
153226
154227 Expect (spec ).ToNot (BeNil ())
228+
229+ // compare
155230 Expect (* spec ).To (BeEquivalentTo (albSpec ))
231+
156232 })
157233
158234 It ("should work with 2 ingresses different path" , func () {
@@ -162,13 +238,19 @@ var _ = Describe("Node Controller", func() {
162238
163239 Expect (k8sClient .Create (context .Background (), & ingress2 )).To (Succeed ())
164240
165- albSpec .Listeners [0 ].Http .Hosts [0 ].Rules = append (
166- albSpec .Listeners [0 ].Http .Hosts [0 ].Rules ,
167- albsdk.Rule {
168- Path : new (albsdk.Path {Prefix : new ("/ foobar ")}),
169- TargetPool : albSpec .Listeners [0 ].Http .Hosts [0 ].Rules [0 ].TargetPool ,
241+ secTargetPool := * albSpec .Listeners [0 ].Http .Hosts [0 ].Rules [0 ].TargetPool
242+ albSpec .Listeners [0 ].Http .Hosts [0 ].Rules = []albsdk.Rule {
243+ {
244+ Path : & albsdk.Path {Prefix : new ("/ foobar ")},
245+ TargetPool : new (secTargetPool ),
246+ WebSocket : new (false ),
247+ },
248+ {
249+ Path : & albsdk.Path {Prefix : new ("/ ")},
250+ TargetPool : new (secTargetPool ),
170251 WebSocket : new (false ),
171- })
252+ },
253+ }
172254
173255 spec , errorEventList , err := reconciler .getAlbSpecForIngressClass (context .Background (), & ingressClass )
174256 Expect (err ).To (Succeed ())
@@ -209,3 +291,90 @@ func testIngress(class *networkingv1.IngressClass, service *corev1.Service) netw
209291 },
210292 }
211293}
294+
295+ func testHttpsIngress (class * networkingv1.IngressClass , service * corev1.Service ) networkingv1.Ingress {
296+ return networkingv1.Ingress {
297+ ObjectMeta : metav1.ObjectMeta {Name : "test-https-ingress" },
298+ Spec : networkingv1.IngressSpec {
299+ IngressClassName : new (class.Name ),
300+ TLS : []networkingv1.IngressTLS {
301+ {
302+ Hosts : []string {"secure.example.com" },
303+ SecretName : "my-secret-cert" ,
304+ },
305+ },
306+ Rules : []networkingv1.IngressRule {
307+ {
308+ Host : "secure.example.com" ,
309+ IngressRuleValue : networkingv1.IngressRuleValue {
310+ HTTP : & networkingv1.HTTPIngressRuleValue {
311+ Paths : []networkingv1.HTTPIngressPath {
312+ {
313+ Path : "/" ,
314+ PathType : new (networkingv1.PathTypePrefix ),
315+ Backend : networkingv1.IngressBackend {
316+ Service : & networkingv1.IngressServiceBackend {
317+ Name : service .Name ,
318+ Port : networkingv1.ServiceBackendPort {Number : service .Spec .Ports [0 ].Port },
319+ },
320+ },
321+ },
322+ },
323+ },
324+ },
325+ },
326+ },
327+ },
328+ }
329+ }
330+
331+ // Returns a clean, isolated Port 80 HTTP Listener structure payload
332+ func testHttpListener (nodePort int32 ) albsdk.Listener {
333+ return albsdk.Listener {
334+ Name : new ("80 - http "),
335+ Port : new (int32 (80 )),
336+ Protocol : new ("PROTOCOL_HTTP "),
337+ Http : & albsdk.ProtocolOptionsHTTP {
338+ Hosts : []albsdk.HostConfig {
339+ {
340+ Host : new ("example.com "),
341+ Rules : []albsdk.Rule {
342+ {
343+ Path : & albsdk.Path {Prefix : new ("/ ")},
344+ TargetPool : new (fmt .Sprintf ("port-%d" , nodePort )),
345+ WebSocket : new (false ),
346+ },
347+ },
348+ },
349+ },
350+ },
351+ }
352+ }
353+
354+ // Returns a clean, isolated Port 443 HTTPS Listener structure payload containing certificate tracking parameters
355+ func testHttpsListener (nodePort int32 , certID string ) albsdk.Listener {
356+ return albsdk.Listener {
357+ Name : new ("443 - https "),
358+ Port : new (int32 (443 )),
359+ Protocol : new ("PROTOCOL_HTTPS "),
360+ Https : & albsdk.ProtocolOptionsHTTPS {
361+ CertificateConfig : & albsdk.CertificateConfig {
362+ CertificateIds : []string {certID },
363+ },
364+ },
365+ Http : & albsdk.ProtocolOptionsHTTP {
366+ Hosts : []albsdk.HostConfig {
367+ {
368+ Host : new ("secure.example .com "),
369+ Rules : []albsdk.Rule {
370+ {
371+ Path : & albsdk.Path {Prefix : new ("/ ")},
372+ TargetPool : new (fmt .Sprintf ("port-%d" , nodePort )),
373+ WebSocket : new (false ),
374+ },
375+ },
376+ },
377+ },
378+ },
379+ }
380+ }
0 commit comments