-
Notifications
You must be signed in to change notification settings - Fork 322
Add OpenShift Dashboards for GitOps #589
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
Merged
openshift-merge-robot
merged 11 commits into
redhat-developer:master
from
gnunn1:master
Aug 30, 2023
Merged
Changes from 8 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
86e598b
Provision dashboards for OpenShift Console
gnunn1 ae7a1c7
Create constant for dashboards folder path
gnunn1 3191017
Add unit test
gnunn1 033f90f
Improve error message when dashboard namespace is not available
gnunn1 5deab95
Remove redis graph due to upstream bug not exposing stats
gnunn1 cc40c09
Update function name and message as per Jaideep's review comments
gnunn1 ca0bce1
Reconcile dashboards if data in configmap changes
gnunn1 a1937fc
Change name to reconcileDashboards since we are now doing reconciliat…
gnunn1 3ef9687
Continue processing dashboards if error occurs instead of stopping
gnunn1 f76ec95
Merge branch 'master' into master
wtam2018 f8c37ef
Continue processing dashboards if new dashboard creation fails
gnunn1 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,7 +18,10 @@ package controllers | |
|
||
import ( | ||
"context" | ||
"embed" | ||
"fmt" | ||
"path/filepath" | ||
"strings" | ||
|
||
argoapp "github.com/argoproj-labs/argocd-operator/api/v1alpha1" | ||
monitoringv1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1" | ||
|
@@ -41,6 +44,8 @@ const ( | |
readRoleNameFormat = "%s-read" | ||
readRoleBindingNameFormat = "%s-prometheus-k8s-read-binding" | ||
alertRuleName = "gitops-operator-argocd-alerts" | ||
dashboardNamespace = "openshift-config-managed" | ||
dashboardFolder = "dashboards" | ||
) | ||
|
||
type ArgoCDMetricsReconciler struct { | ||
|
@@ -50,6 +55,12 @@ type ArgoCDMetricsReconciler struct { | |
Scheme *runtime.Scheme | ||
} | ||
|
||
// embed json dashboards | ||
var ( | ||
//go:embed dashboards | ||
dashboards embed.FS | ||
) | ||
|
||
// blank assignment to verify that ReconcileArgoCDRoute implements reconcile.Reconciler | ||
var _ reconcile.Reconciler = &ArgoCDMetricsReconciler{} | ||
|
||
|
@@ -154,6 +165,11 @@ func (r *ArgoCDMetricsReconciler) Reconcile(ctx context.Context, request reconci | |
return reconcile.Result{}, err | ||
} | ||
|
||
err = r.reconcileDashboards(reqLogger) | ||
if err != nil { | ||
return reconcile.Result{}, err | ||
} | ||
|
||
return reconcile.Result{}, nil | ||
} | ||
|
||
|
@@ -292,6 +308,94 @@ func (r *ArgoCDMetricsReconciler) createPrometheusRuleIfAbsent(namespace string, | |
return err | ||
} | ||
|
||
func (r *ArgoCDMetricsReconciler) reconcileDashboards(reqLogger logr.Logger) error { | ||
err := r.Client.Get(context.TODO(), types.NamespacedName{Name: dashboardNamespace}, &corev1.Namespace{}) | ||
if err != nil { | ||
reqLogger.Info("Monitoring dashboards are not supported on this cluster, skipping dashboard installation", | ||
"Namespace", dashboardNamespace) | ||
return nil | ||
} | ||
|
||
entries, err := dashboards.ReadDir(dashboardFolder) | ||
if err != nil { | ||
reqLogger.Error(err, "Could not read list of embedded dashboards") | ||
return err | ||
} | ||
|
||
for _, entry := range entries { | ||
reqLogger.Info("Processing dashboard", "Namespace", dashboardNamespace, "Name", entry.Name()) | ||
|
||
if !entry.IsDir() { | ||
dashboard, err := newDashboardConfigMap(entry.Name(), dashboardNamespace) | ||
if err != nil { | ||
reqLogger.Info("There was an error creating dashboard ", "Namespace", dashboardNamespace, "Name", entry.Name()) | ||
return err | ||
} | ||
|
||
existingDashboard := &corev1.ConfigMap{} | ||
|
||
err = r.Client.Get(context.TODO(), types.NamespacedName{Name: dashboard.Name, Namespace: dashboardNamespace}, existingDashboard) | ||
if err == nil { | ||
reqLogger.Info("A dashboard instance already exists", | ||
"Namespace", existingDashboard.Namespace, "Name", existingDashboard.Name) | ||
|
||
// See if we need to reconcile based on dashboard data only to allow users | ||
// to disable dashboard via label if so desired. Note that disabling it | ||
// will be reset if dashboard changes in newer version of operator. | ||
if existingDashboard.Data[entry.Name()] != dashboard.Data[entry.Name()] { | ||
reqLogger.Info("Dashboard data does not match expectation, reconciling", | ||
"Namespace", dashboard.Namespace, "Name", dashboard.Name) | ||
err := r.Client.Update(context.TODO(), dashboard) | ||
if err != nil { | ||
reqLogger.Error(err, "Error updating dashboard", | ||
"Namespace", dashboard.Namespace, "Name", dashboard.Name) | ||
return err | ||
} | ||
} | ||
continue | ||
} | ||
|
||
if errors.IsNotFound(err) { | ||
reqLogger.Info("Creating new dashboard", | ||
"Namespace", dashboard.Namespace, "Name", dashboard.Name) | ||
err := r.Client.Create(context.TODO(), dashboard) | ||
if err != nil { | ||
reqLogger.Error(err, "Error creating a new dashboard", | ||
"Namespace", dashboard.Namespace, "Name", dashboard.Name) | ||
// Should we return an error or continue with other dashboards? | ||
return err | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should continue with other dashboards here, unless they only make sense in context of each other. same for line 332 as well |
||
} | ||
} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func newDashboardConfigMap(filename string, namespace string) (*corev1.ConfigMap, error) { | ||
|
||
name := strings.TrimSuffix(filename, filepath.Ext(filename)) | ||
|
||
objectMeta := metav1.ObjectMeta{ | ||
Name: name, | ||
Namespace: namespace, | ||
Labels: map[string]string{ | ||
"console.openshift.io/dashboard": "true", | ||
}, | ||
} | ||
|
||
content, err := dashboards.ReadFile(dashboardFolder + "/" + filename) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &corev1.ConfigMap{ | ||
ObjectMeta: objectMeta, | ||
Data: map[string]string{ | ||
filename: string(content), | ||
}, | ||
}, nil | ||
} | ||
|
||
func newReadRole(namespace string) *rbacv1.Role { | ||
objectMeta := metav1.ObjectMeta{ | ||
Name: fmt.Sprintf(readRoleNameFormat, namespace), | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.