From a32e0463ded0bd2c3d1f8657359d36fb4eec8832 Mon Sep 17 00:00:00 2001
From: Jacob Baungard Hansen <jacobbaungard@redhat.com>
Date: Fri, 22 Nov 2024 12:15:32 +0100
Subject: [PATCH] Renderer: detect if imagestream is available

Only try to get the oauth image from the OCP imagestream, if the
image.openshift.io api type is available. Otherwise, it likely means
we're running a non-ocp system (for kind tests for example) and in this
case we accept using the base template image.

Signed-off-by: Jacob Baungard Hansen <jacobbaungard@redhat.com>
---
 .../pkg/rendering/renderer.go                 | 20 +++++++++++++++++++
 .../pkg/rendering/renderer_alertmanager.go    | 20 ++++++++++++++-----
 .../pkg/rendering/renderer_grafana.go         | 20 ++++++++++++++-----
 .../pkg/rendering/renderer_proxy.go           | 20 ++++++++++++++-----
 4 files changed, 65 insertions(+), 15 deletions(-)

diff --git a/operators/multiclusterobservability/pkg/rendering/renderer.go b/operators/multiclusterobservability/pkg/rendering/renderer.go
index ef3651d5d4..b9596cc4bf 100644
--- a/operators/multiclusterobservability/pkg/rendering/renderer.go
+++ b/operators/multiclusterobservability/pkg/rendering/renderer.go
@@ -10,6 +10,7 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/client-go/discovery"
 	logf "sigs.k8s.io/controller-runtime/pkg/log"
 
 	obv1beta2 "github.com/stolostron/multicluster-observability-operator/operators/multiclusterobservability/api/v1beta2"
@@ -193,3 +194,22 @@ func (r *MCORenderer) MCOAResources(namespace string, labels map[string]string)
 
 	return mcoaResources, nil
 }
+
+func (r *MCORenderer) HasImagestream() (bool, error) {
+	dcl := discovery.NewDiscoveryClient(r.imageClient.RESTClient())
+
+	apiList, err := dcl.ServerGroups()
+	if err != nil {
+		log.Error(err, "unable to get ServerGroups from imagestream detection")
+		return false, err
+	}
+
+	apiGroups := apiList.Groups
+	for i := 0; i < len(apiGroups); i++ {
+		if apiGroups[i].Name == "image.openshift.io" {
+			return true, nil
+		}
+	}
+
+	return false, nil
+}
diff --git a/operators/multiclusterobservability/pkg/rendering/renderer_alertmanager.go b/operators/multiclusterobservability/pkg/rendering/renderer_alertmanager.go
index 978feb25a9..a752665452 100644
--- a/operators/multiclusterobservability/pkg/rendering/renderer_alertmanager.go
+++ b/operators/multiclusterobservability/pkg/rendering/renderer_alertmanager.go
@@ -123,11 +123,21 @@ func (r *MCORenderer) renderAlertManagerStatefulSet(res *resource.Resource, name
 		configReloaderContainer.Image = image
 	}
 
-	found, image = mcoconfig.GetOauthProxyImage(r.imageClient)
-	if found {
-		oauthProxyContainer.Image = image
-	} else {
-		return nil, fmt.Errorf("failed to get OAuth image for alertmanager")
+	hasImagestream, err := r.HasImagestream()
+	if err != nil {
+		return nil, err
+	}
+
+	// If we're on OCP and has imagestreams, we always want the oauth image
+	// from the imagestream, and fail the reconcile if we don't find it.
+	// If we're on non-OCP (tests) we use the base template image
+	if hasImagestream {
+		found, image = mcoconfig.GetOauthProxyImage(r.imageClient)
+		if found {
+			oauthProxyContainer.Image = image
+		} else {
+			return nil, fmt.Errorf("failed to get OAuth image for alertmanager")
+		}
 	}
 	oauthProxyContainer.ImagePullPolicy = imagePullPolicy
 
diff --git a/operators/multiclusterobservability/pkg/rendering/renderer_grafana.go b/operators/multiclusterobservability/pkg/rendering/renderer_grafana.go
index 49ef1de519..ae4a38fed2 100644
--- a/operators/multiclusterobservability/pkg/rendering/renderer_grafana.go
+++ b/operators/multiclusterobservability/pkg/rendering/renderer_grafana.go
@@ -70,11 +70,21 @@ func (r *MCORenderer) renderGrafanaDeployments(res *resource.Resource,
 	}
 	spec.Containers[1].ImagePullPolicy = imagePullPolicy
 
-	found, image = config.GetOauthProxyImage(r.imageClient)
-	if found {
-		spec.Containers[2].Image = image
-	} else {
-		return nil, fmt.Errorf("failed to get OAuth image for Grafana")
+	hasImagestream, err := r.HasImagestream()
+	if err != nil {
+		return nil, err
+	}
+
+	// If we're on OCP and has imagestreams, we always want the oauth image
+	// from the imagestream, and fail the reconcile if we don't find it.
+	// If we're on non-OCP (tests) we use the base template image
+	if hasImagestream {
+		found, image = config.GetOauthProxyImage(r.imageClient)
+		if found {
+			spec.Containers[2].Image = image
+		} else {
+			return nil, fmt.Errorf("failed to get OAuth image for alertmanager")
+		}
 	}
 	spec.Containers[2].ImagePullPolicy = imagePullPolicy
 
diff --git a/operators/multiclusterobservability/pkg/rendering/renderer_proxy.go b/operators/multiclusterobservability/pkg/rendering/renderer_proxy.go
index d0cff6f177..9c177f13ed 100644
--- a/operators/multiclusterobservability/pkg/rendering/renderer_proxy.go
+++ b/operators/multiclusterobservability/pkg/rendering/renderer_proxy.go
@@ -94,11 +94,21 @@ func (r *MCORenderer) renderProxyDeployment(res *resource.Resource,
 		spec.Containers[0].Image = image
 	}
 
-	found, image = mcoconfig.GetOauthProxyImage(r.imageClient)
-	if found {
-		spec.Containers[1].Image = image
-	} else {
-		return nil, fmt.Errorf("failed to get OAuth image for rbacqueryproxy")
+	hasImagestream, err := r.HasImagestream()
+	if err != nil {
+		return nil, err
+	}
+
+	// If we're on OCP and has imagestreams, we always want the oauth image
+	// from the imagestream, and fail the reconcile if we don't find it.
+	// If we're on non-OCP (tests) we use the base template image
+	if hasImagestream {
+		found, image = mcoconfig.GetOauthProxyImage(r.imageClient)
+		if found {
+			spec.Containers[1].Image = image
+		} else {
+			return nil, fmt.Errorf("failed to get OAuth image for alertmanager")
+		}
 	}
 
 	for idx := range spec.Volumes {