Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get Oauth proxy image from ImageStreams resource #1587

Merged
merged 20 commits into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cicd-scripts/setup-e2e-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ deploy_mco_operator() {
cd ${ROOTDIR}/operators/multiclusterobservability/config/manager && kustomize edit set image quay.io/stolostron/multicluster-observability-operator="${IMAGE_REPO}/multicluster-observability-operator:${LATEST_SNAPSHOT}"
fi
cd ${ROOTDIR}
kustomize build ${ROOTDIR}/operators/multiclusterobservability/config/default | kubectl apply -n ${OCM_DEFAULT_NS} --server-side=true -f -
kustomize build ${ROOTDIR}/operators/multiclusterobservability/config/default | kubectl apply -n ${OCM_DEFAULT_NS} --server-side=true --force-conflicts -f -

# wait until mco is ready
wait_for_deployment_ready 10 60s ${OCM_DEFAULT_NS} multicluster-observability-operator
Expand Down
2 changes: 1 addition & 1 deletion loaders/dashboards/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Copyright Contributors to the Open Cluster Management project

FROM registry.ci.openshift.org/stolostron/builder:go1.21-linux AS builder
FROM registry.ci.openshift.org/stolostron/builder:go1.22-linux AS builder

WORKDIR /workspace
COPY go.sum go.mod ./loaders/dashboards ./
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import (
"strings"
"time"

imagev1 "github.com/openshift/api/image/v1"
imagev1client "github.com/openshift/client-go/image/clientset/versioned/typed/image/v1"

operatorconfig "github.com/stolostron/multicluster-observability-operator/operators/pkg/config"
addonv1alpha1 "open-cluster-management.io/api/addon/v1alpha1"

Expand Down Expand Up @@ -80,13 +83,14 @@ var (

// MultiClusterObservabilityReconciler reconciles a MultiClusterObservability object
type MultiClusterObservabilityReconciler struct {
Manager manager.Manager
Client client.Client
Log logr.Logger
Scheme *runtime.Scheme
CRDMap map[string]bool
APIReader client.Reader
RESTMapper meta.RESTMapper
Manager manager.Manager
Client client.Client
Log logr.Logger
Scheme *runtime.Scheme
CRDMap map[string]bool
APIReader client.Reader
RESTMapper meta.RESTMapper
ImageClient *imagev1client.ImageV1Client
}

// +kubebuilder:rbac:groups=observability.open-cluster-management.io,resources=multiclusterobservabilities,verbs=get;list;watch;create;update;patch;delete
Expand Down Expand Up @@ -250,8 +254,9 @@ func (r *MultiClusterObservabilityReconciler) Reconcile(ctx context.Context, req
return ctrl.Result{}, err
}
instance.Spec.StorageConfig.StorageClass = storageClassSelected

// Render the templates with a specified CR
renderer := rendering.NewMCORenderer(instance, r.Client)
renderer := rendering.NewMCORenderer(instance, r.Client, r.ImageClient)
toDeploy, err := renderer.Render()
if err != nil {
reqLogger.Error(err, "Failed to render multiClusterMonitoring templates")
Expand Down Expand Up @@ -448,7 +453,6 @@ func (r *MultiClusterObservabilityReconciler) SetupWithManager(mgr ctrl.Manager)
cmPred := GetConfigMapPredicateFunc()
secretPred := GetAlertManagerSecretPredicateFunc()
namespacePred := GetNamespacePredicateFunc()

ctrBuilder := ctrl.NewControllerManagedBy(mgr).
// Watch for changes to primary resource MultiClusterObservability with predicate
For(&mcov1beta2.MultiClusterObservability{}, builder.WithPredicates(mcoPred)).
Expand Down Expand Up @@ -489,6 +493,23 @@ func (r *MultiClusterObservabilityReconciler) SetupWithManager(mgr ctrl.Manager)
return nil
}), builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}))

if _, err := mgr.GetRESTMapper().KindFor(schema.GroupVersionResource{
Group: "image.openshift.io",
Version: "v1",
Resource: "imagestreams",
}); err != nil {
if meta.IsNoMatchError(err) {
log.Info("image.openshift.io/v1/imagestreams is not available")
} else {
log.Error(err, "failed to get kind for image.openshift.io/v1/imagestreams")
os.Exit(1)
}
} else {
// Images stream is only available in OpenShift
imageStreamPred := GetImageStreamPredicateFunc()
ctrBuilder = ctrBuilder.Watches(&imagev1.ImageStream{}, &handler.EnqueueRequestForObject{}, builder.WithPredicates(imageStreamPred))
}

mchGroupKind := schema.GroupKind{Group: mchv1.GroupVersion.Group, Kind: "MultiClusterHub"}
if _, err := r.RESTMapper.RESTMapping(mchGroupKind, mchv1.GroupVersion.Version); err == nil {
mchPred := GetMCHPredicateFunc(c)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,3 +189,20 @@ func GetNamespacePredicateFunc() predicate.Funcs {
},
}
}

func GetImageStreamPredicateFunc() predicate.Funcs {
return predicate.Funcs{
CreateFunc: func(e event.CreateEvent) bool {
return e.Object.GetName() == config.OauthProxyImageStreamName
},
UpdateFunc: func(e event.UpdateEvent) bool {
if e.ObjectNew.GetName() != config.OauthProxyImageStreamName {
return false
}
return e.ObjectOld.GetGeneration() != e.ObjectNew.GetGeneration()
},
DeleteFunc: func(e event.DeleteEvent) bool {
return false
},
}
}
25 changes: 18 additions & 7 deletions operators/multiclusterobservability/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import (
"fmt"
"os"

imagev1 "github.com/openshift/api/image/v1"

imagev1client "github.com/openshift/client-go/image/clientset/versioned/typed/image/v1"
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
// to ensure that exec-entrypoint and run can make use of them.

Expand Down Expand Up @@ -69,6 +72,7 @@ func init() {
utilruntime.Must(observatoriumAPIs.AddToScheme(scheme))
utilruntime.Must(prometheusv1.AddToScheme(scheme))
utilruntime.Must(addonv1alpha1.AddToScheme(scheme))
utilruntime.Must(imagev1.AddToScheme(scheme))
// +kubebuilder:scaffold:scheme
}

Expand Down Expand Up @@ -282,14 +286,21 @@ func main() {
config.MCGHCrdName: mcghCrdExists,
}

imageClient, err := imagev1client.NewForConfig(ctrl.GetConfigOrDie())
if err != nil {
setupLog.Error(err, "failed to create openshift image client")
os.Exit(1)
}

if err = (&mcoctrl.MultiClusterObservabilityReconciler{
Manager: mgr,
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("MultiClusterObservability"),
Scheme: mgr.GetScheme(),
CRDMap: crdMaps,
APIReader: mgr.GetAPIReader(),
RESTMapper: mgr.GetRESTMapper(),
Manager: mgr,
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("MultiClusterObservability"),
Scheme: mgr.GetScheme(),
CRDMap: crdMaps,
APIReader: mgr.GetAPIReader(),
RESTMapper: mgr.GetRESTMapper(),
ImageClient: imageClient,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "MultiClusterObservability")
os.Exit(1)
Expand Down
37 changes: 32 additions & 5 deletions operators/multiclusterobservability/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
"fmt"
"net/url"
"os"
"reflect"
"strings"
"time"

imagev1client "github.com/openshift/client-go/image/clientset/versioned/typed/image/v1"

ocinfrav1 "github.com/openshift/api/config/v1"
operatorv1 "github.com/openshift/api/operator/v1"
routev1 "github.com/openshift/api/route/v1"
Expand Down Expand Up @@ -148,11 +151,6 @@
KubeRBACProxyKey = "kube_rbac_proxy"
KubeRBACProxyImgName = "kube-rbac-proxy"

OauthProxyImgRepo = "quay.io/stolostron"
OauthProxyImgName = "origin-oauth-proxy"
OauthProxyImgTagSuffix = "2.0.12-SNAPSHOT-2021-06-11-19-40-10"
OauthProxyKey = "oauth_proxy"

EndpointControllerImgName = "endpoint-monitoring-operator"
EndpointControllerKey = "endpoint_monitoring_operator"

Expand Down Expand Up @@ -219,6 +217,11 @@
HubEndpointSaName = "endpoint-observability-operator-sa"
)

const (
OauthProxyImageStreamName = "oauth-proxy"
OauthProxyImageStreamNamespace = "openshift"
)

// ObjectStorgeConf is used to Unmarshal from bytes to do validation.
type ObjectStorgeConf struct {
Type string `yaml:"type"`
Expand Down Expand Up @@ -564,7 +567,7 @@

// GetClusterID is used to get the cluster uid.
func GetClusterID(ocpClient ocpClientSet.Interface) (string, error) {
clusterVersion, err := ocpClient.ConfigV1().ClusterVersions().Get(context.TODO(), "version", v1.GetOptions{})

Check failure on line 570 in operators/multiclusterobservability/pkg/config/config.go

View workflow job for this annotation

GitHub Actions / Formatters + Linters (Static Analysis) for Go

ocpClient.ConfigV1().ClusterVersions undefined (type "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1".ConfigV1Interface has no field or method ClusterVersions)
if err != nil {
log.Error(err, "Failed to get clusterVersion")
return "", err
Expand Down Expand Up @@ -828,3 +831,27 @@
annotations := mco.GetAnnotations()
return annotations != nil && annotations[AnnotationDisableMCOAlerting] == "true"
}

func GetOauthProxyImage(imageClient imagev1client.ImageV1Interface) (bool, string) {
if imageClient != nil && !reflect.ValueOf(imageClient).IsNil() {
// set oauth-proxy from imagestream.image.openshift.io
oauthImageStream, err := imageClient.ImageStreams(OauthProxyImageStreamNamespace).
Get(context.TODO(), OauthProxyImageStreamName, v1.GetOptions{})
if err != nil {
if !errors.IsNotFound(err) {
return false, ""
}
// do not expect error = IsNotFound in OCP environment.
// But for e2e test, it can be. for this case, just ignore
} else {
if oauthImageStream.Spec.Tags != nil {
tag := oauthImageStream.Spec.Tags[0]
if tag.From != nil && tag.From.Kind == "DockerImage" && len(tag.From.Name) > 0 {
return true, tag.From.Name
}
}
}
}
return false, ""

}
11 changes: 7 additions & 4 deletions operators/multiclusterobservability/pkg/rendering/renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package rendering

import (
imagev1client "github.com/openshift/client-go/image/clientset/versioned/typed/image/v1"
v1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
Expand All @@ -24,6 +25,7 @@ var log = logf.Log.WithName("renderer")

type MCORenderer struct {
kubeClient client.Client
imageClient *imagev1client.ImageV1Client
renderer *rendererutil.Renderer
cr *obv1beta2.MultiClusterObservability
renderGrafanaFns map[string]rendererutil.RenderFn
Expand All @@ -33,11 +35,12 @@ type MCORenderer struct {
renderMCOAFns map[string]rendererutil.RenderFn
}

func NewMCORenderer(multipleClusterMonitoring *obv1beta2.MultiClusterObservability, kubeClient client.Client) *MCORenderer {
func NewMCORenderer(multipleClusterMonitoring *obv1beta2.MultiClusterObservability, kubeClient client.Client, imageClient *imagev1client.ImageV1Client) *MCORenderer {
mcoRenderer := &MCORenderer{
renderer: rendererutil.NewRenderer(),
cr: multipleClusterMonitoring,
kubeClient: kubeClient,
renderer: rendererutil.NewRenderer(),
cr: multipleClusterMonitoring,
kubeClient: kubeClient,
imageClient: imageClient,
}
mcoRenderer.newGranfanaRenderer()
mcoRenderer.newAlertManagerRenderer()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,8 @@ func (r *MCORenderer) renderAlertManagerStatefulSet(res *resource.Resource,
if found {
spec.Containers[1].Image = image
}
// the oauth-proxy image only exists in mch-image-manifest configmap
// pass nil annotation to make sure oauth-proxy overrided from mch-image-manifest
found, image = mcoconfig.ReplaceImage(nil, mcoconfig.OauthProxyImgRepo,
mcoconfig.OauthProxyKey)

found, image = mcoconfig.GetOauthProxyImage(r.imageClient)
if found {
spec.Containers[2].Image = image
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,9 @@ func TestAlertManagerRenderer(t *testing.T) {
}

containerNameToMchKey := map[string]string{
"alertmanager": "prometheus_alertmanager",
"config-reloader": "configmap_reloader",
"alertmanager-proxy": "oauth_proxy",
"kube-rbac-proxy": "kube_rbac_proxy",
"alertmanager": "prometheus_alertmanager",
"config-reloader": "configmap_reloader",
"kube-rbac-proxy": "kube_rbac_proxy",
}
mchImageManifest := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Expand All @@ -57,12 +56,12 @@ func TestAlertManagerRenderer(t *testing.T) {
Data: map[string]string{
"prometheus_alertmanager": "quay.io/rhacm2/alertmanager:latest",
"configmap_reloader": "quay.io/rhacm2/configmap-reloader:latest",
"oauth_proxy": "quay.io/rhacm2/oauth_proxy:latest",
"kube_rbac_proxy": "quay.io/rhacm2/kube-rbac-proxy:latest",
},
}

kubeClient := fake.NewClientBuilder().WithObjects(clientCa, mchImageManifest).Build()

alertResources := renderTemplates(t, kubeClient, makeBaseMco())

// clientCa configmap must be filled with the client-ca-file data
Expand All @@ -75,6 +74,11 @@ func TestAlertManagerRenderer(t *testing.T) {
sts := &appsv1.StatefulSet{}
runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, sts)
for _, container := range sts.Spec.Template.Spec.Containers {
// oauth-proxy container is not in the mch-image-manifest configmap
// we use image-streams to get image for oauth-proxy
if container.Name == "alertmanager-proxy" {
continue
}
assert.Equal(t, mchImageManifest.Data[containerNameToMchKey[container.Name]], container.Image)
}
}
Expand Down Expand Up @@ -237,7 +241,7 @@ func renderTemplates(t *testing.T, kubeClient client.Client, mco *mcov1beta2.Mul
defer os.Unsetenv(templatesutil.TemplatesPathEnvVar)

config.ReadImageManifestConfigMap(kubeClient, "v1")
renderer := NewMCORenderer(mco, kubeClient)
renderer := NewMCORenderer(mco, kubeClient, nil)

//load and render alertmanager templates
alertTemplates, err := templates.GetOrLoadAlertManagerTemplates(templatesutil.GetTemplateRenderer())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ func (r *MCORenderer) renderGrafanaDeployments(res *resource.Resource,
}
spec.Containers[1].ImagePullPolicy = imagePullPolicy

found, image = config.ReplaceImage(nil, config.OauthProxyImgRepo,
config.OauthProxyKey)
found, image = config.GetOauthProxyImage(r.imageClient)
if found {
spec.Containers[2].Image = image
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,7 @@ func (r *MCORenderer) renderProxyDeployment(res *resource.Resource,
spec.Containers[0].Image = image
}

// the oauth-proxy image only exists in mch-image-manifest configmap
// pass nil annotation to make sure oauth-proxy overrided from mch-image-manifest
found, image = mcoconfig.ReplaceImage(nil, mcoconfig.OauthProxyImgRepo,
mcoconfig.OauthProxyKey)
found, image = mcoconfig.GetOauthProxyImage(r.imageClient)
if found {
spec.Containers[1].Image = image
}
Expand Down
Loading
Loading