From 489411d4688b91749c465f39fc5947e8909c55d5 Mon Sep 17 00:00:00 2001
From: phantomjinx
Date: Fri, 12 Jan 2024 19:11:25 +0000
Subject: [PATCH] feat: Adds notional support for extracting the url into the
hawtio.Status
* While the extraction of the route url is quite straightforward, the
use of ingress path rules and no hosts makes the return of a single
string quite difficult. This may well need work in the future to
improve the value returned
---
pkg/controller/hawtio/hawtio_controller.go | 3 +
pkg/resources/kubernetes/ingress.go | 71 +++++++++++++++++++++
pkg/resources/kubernetes/ingress_test.go | 73 ++++++++++++++++++++++
3 files changed, 147 insertions(+)
create mode 100644 pkg/resources/kubernetes/ingress_test.go
diff --git a/pkg/controller/hawtio/hawtio_controller.go b/pkg/controller/hawtio/hawtio_controller.go
index efdd91f345..dd750c97cb 100644
--- a/pkg/controller/hawtio/hawtio_controller.go
+++ b/pkg/controller/hawtio/hawtio_controller.go
@@ -541,6 +541,9 @@ func (r *ReconcileHawtio) Reconcile(request reconcile.Request) (reconcile.Result
// And requeue to create a new route in the next reconcile loop
return reconcile.Result{Requeue: true}, nil
}
+ } else {
+ ingressRouteURL = kresources.GetIngressURL(ingress)
+ hawtioCopy.Status.URL = ingressRouteURL
}
// Reconcile console link in OpenShift console
diff --git a/pkg/resources/kubernetes/ingress.go b/pkg/resources/kubernetes/ingress.go
index a29b248a4b..c5b5913fb7 100644
--- a/pkg/resources/kubernetes/ingress.go
+++ b/pkg/resources/kubernetes/ingress.go
@@ -1,6 +1,8 @@
package kubernetes
import (
+ "strconv"
+
hawtiov1 "github.com/hawtio/hawtio-operator/pkg/apis/hawtio/v1"
corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
@@ -67,3 +69,72 @@ func NewIngress(hawtio *hawtiov1.Hawtio, servingSecret *corev1.Secret) *networki
return ingress
}
+
+// GetIngressURL determines the full URL of the given ingress
+func GetIngressURL(ingress *networkingv1.Ingress) string {
+ var scheme string
+ if len(ingress.Spec.TLS) > 0 {
+ scheme = "https"
+ } else {
+ scheme = "http"
+ }
+
+ host, port := getIngressHostAndPort(ingress)
+ path := getIngressPath(ingress)
+
+ url := scheme + "://" + host
+ if len(port) > 0 {
+ url = url + ":" + port
+ }
+
+ return url + path
+}
+
+func getIngressHostAndPort(ingress *networkingv1.Ingress) (string, string) {
+ ingressStatuses := ingress.Status.LoadBalancer.Ingress
+ if len(ingressStatuses) == 0 {
+ for _, ingressRule := range ingress.Spec.Rules {
+ if len(ingressRule.Host) > 0 {
+ return ingressRule.Host, ""
+ }
+ }
+
+ return "*", "" // host must be a wildcard
+ }
+
+ // get host or ip of the first ingress status available
+ var host string
+ port := ""
+ for _, ingressStatus := range ingress.Status.LoadBalancer.Ingress {
+ if len(ingressStatus.Hostname) > 0 {
+ host = ingressStatus.Hostname
+ } else if len(ingressStatus.IP) > 0 {
+ host = ingressStatus.IP
+ }
+
+ if len(host) > 0 {
+ for _, statusPort := range ingressStatus.Ports {
+ port = strconv.FormatInt(int64(statusPort.Port), 10)
+ continue // get the first port
+ }
+ }
+ }
+
+ if len(host) == 0 {
+ return "*", port
+ }
+
+ return host, port
+}
+
+func getIngressPath(ingress *networkingv1.Ingress) string {
+ for _, ingressRule := range ingress.Spec.Rules {
+ if ingressRule.IngressRuleValue.HTTP != nil {
+ for _, httpPath := range ingressRule.IngressRuleValue.HTTP.Paths {
+ return httpPath.Path
+ }
+ }
+ }
+
+ return "/"
+}
diff --git a/pkg/resources/kubernetes/ingress_test.go b/pkg/resources/kubernetes/ingress_test.go
new file mode 100644
index 0000000000..c57c490532
--- /dev/null
+++ b/pkg/resources/kubernetes/ingress_test.go
@@ -0,0 +1,73 @@
+package kubernetes
+
+import (
+ "testing"
+
+ corev1 "k8s.io/api/core/v1"
+ networkingv1 "k8s.io/api/networking/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+ "github.com/hawtio/hawtio-operator/pkg/resources"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestGetIngressURL(t *testing.T) {
+ annotations := map[string]string{}
+ annotations["nginx.ingress.kubernetes.io/backend-protocol"] = "HTTPS"
+ annotations["nginx.ingress.kubernetes.io/force-ssl-redirect"] = "true"
+ annotations["nginx.ingress.kubernetes.io/rewrite-target"] = "/$1"
+
+ labels := map[string]string{
+ resources.LabelAppKey: "hawtio",
+ }
+ pathPrefix := networkingv1.PathTypePrefix
+ name := "hawtio-online"
+
+ ingress := &networkingv1.Ingress{
+ ObjectMeta: metav1.ObjectMeta{
+ Annotations: annotations,
+ Labels: labels,
+ Name: name,
+ },
+ Spec: networkingv1.IngressSpec{
+ TLS: []networkingv1.IngressTLS{
+ {
+ SecretName: "some-tls-secret",
+ },
+ },
+ Rules: []networkingv1.IngressRule{
+ {
+ IngressRuleValue: networkingv1.IngressRuleValue{
+ HTTP: &networkingv1.HTTPIngressRuleValue{
+ Paths: []networkingv1.HTTPIngressPath{{
+ Path: "/(.*)",
+ PathType: &pathPrefix,
+ Backend: networkingv1.IngressBackend{
+ Service: &networkingv1.IngressServiceBackend{
+ Name: name,
+ Port: networkingv1.ServiceBackendPort{
+ Number: 443,
+ },
+ },
+ },
+ }},
+ },
+ },
+ },
+ },
+ },
+ Status: networkingv1.IngressStatus{
+ LoadBalancer: corev1.LoadBalancerStatus{
+ Ingress: []corev1.LoadBalancerIngress{
+ {
+ IP: "192.168.99.9",
+ },
+ },
+ },
+ },
+ }
+
+ url := GetIngressURL(ingress)
+ assert.Equal(t, "https://192.168.99.9/(.*)", url)
+}