Skip to content

Commit c22ca97

Browse files
Merge pull request #328 from csibbitt/csibbitt/OSPRH-4384_dashboards
Adding Console UI Dashboards automation
2 parents 3944553 + 1baada6 commit c22ca97

13 files changed

+2463
-2
lines changed

api/bases/telemetry.openstack.org_metricstorages.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,11 @@ spec:
10251025
default: true
10261026
description: AlertingEnabled allows to enable or disable alertmanager
10271027
type: boolean
1028+
dashboardsEnabled:
1029+
default: false
1030+
description: DashboardsEnabled allows to enable or disable dashboards
1031+
and related artifacts
1032+
type: boolean
10281033
dataplaneNetwork:
10291034
default: ctlplane
10301035
description: DataplaneNetwork defines the network that will be

api/bases/telemetry.openstack.org_telemetries.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,6 +1532,11 @@ spec:
15321532
default: true
15331533
description: AlertingEnabled allows to enable or disable alertmanager
15341534
type: boolean
1535+
dashboardsEnabled:
1536+
default: false
1537+
description: DashboardsEnabled allows to enable or disable
1538+
dashboards and related artifacts
1539+
type: boolean
15351540
dataplaneNetwork:
15361541
default: ctlplane
15371542
description: DataplaneNetwork defines the network that will

api/v1beta1/conditions.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ const (
4747

4848
// LoggingReadyCondition Status=True condition which indicates if the Logging is configured and operational
4949
LoggingReadyCondition condition.Type = "LoggingReady"
50+
51+
DashboardPrometheusRuleReadyCondition condition.Type = "DashboardPrometheusRuleReady"
52+
53+
DashboardDatasourceReadyCondition condition.Type = "DashboardDatasourceReady"
54+
55+
DashboardDefinitionReadyCondition condition.Type = "DashboardDefinitionReady"
5056
)
5157

5258
// Telemetry Reasons used by API objects.
@@ -170,4 +176,16 @@ const (
170176

171177
// LoggingReadyRunningMessage
172178
LoggingReadyRunningMessage = "Logging in progress"
179+
180+
DashboardsNotEnabledMessage = "Dashboarding was not enabled, so no actions required"
181+
182+
DashboardPrometheusRuleReadyInitMessage = "Dashboard PrometheusRule not started"
183+
DashboardPrometheusRuleUnableToOwnMessage = "Error occured when trying to own %s"
184+
185+
DashboardDatasourceReadyInitMessage = "Dashboard Datasource not started"
186+
DashboardDatasourceFailedMessage = "Error occured when trying to install the dashboard datasource: %s"
187+
188+
DashboardDefinitionReadyInitMessage = "Dashboard Definition not started"
189+
DashboardDefinitionFailedMessage = "Error occured when trying to install the dashboard definitions: %s"
190+
173191
)

api/v1beta1/metricstorage_types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ type MonitoringStack struct {
6666
// +kubebuilder:default=true
6767
AlertingEnabled bool `json:"alertingEnabled"`
6868

69+
// DashboardsEnabled allows to enable or disable dashboards and related artifacts
70+
// +kubebuilder:validation:Optional
71+
// +kubebuilder:default=false
72+
DashboardsEnabled bool `json:"dashboardsEnabled"`
73+
6974
// ScrapeInterval sets the interval between scrapes
7075
// +kubebuilder:validation:Optional
7176
// +kubebuilder:default="30s"

config/crd/bases/telemetry.openstack.org_metricstorages.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,11 @@ spec:
10251025
default: true
10261026
description: AlertingEnabled allows to enable or disable alertmanager
10271027
type: boolean
1028+
dashboardsEnabled:
1029+
default: false
1030+
description: DashboardsEnabled allows to enable or disable dashboards
1031+
and related artifacts
1032+
type: boolean
10281033
dataplaneNetwork:
10291034
default: ctlplane
10301035
description: DataplaneNetwork defines the network that will be

config/crd/bases/telemetry.openstack.org_telemetries.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,6 +1532,11 @@ spec:
15321532
default: true
15331533
description: AlertingEnabled allows to enable or disable alertmanager
15341534
type: boolean
1535+
dashboardsEnabled:
1536+
default: false
1537+
description: DashboardsEnabled allows to enable or disable
1538+
dashboards and related artifacts
1539+
type: boolean
15351540
dataplaneNetwork:
15361541
default: ctlplane
15371542
description: DataplaneNetwork defines the network that will

config/rbac/role.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,18 @@ rules:
206206
- patch
207207
- update
208208
- watch
209+
- apiGroups:
210+
- monitoring.rhobs
211+
resources:
212+
- prometheusrules
213+
verbs:
214+
- create
215+
- delete
216+
- get
217+
- list
218+
- patch
219+
- update
220+
- watch
209221
- apiGroups:
210222
- monitoring.rhobs
211223
resources:

controllers/metricstorage_controller.go

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"reflect"
2424
"regexp"
2525

26+
corev1 "k8s.io/api/core/v1"
2627
discoveryv1 "k8s.io/api/discovery/v1"
2728
k8s_errors "k8s.io/apimachinery/pkg/api/errors"
2829
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -52,6 +53,7 @@ import (
5253
infranetworkv1 "github.com/openstack-k8s-operators/infra-operator/apis/network/v1beta1"
5354
telemetryv1 "github.com/openstack-k8s-operators/telemetry-operator/api/v1beta1"
5455
ceilometer "github.com/openstack-k8s-operators/telemetry-operator/pkg/ceilometer"
56+
"github.com/openstack-k8s-operators/telemetry-operator/pkg/dashboards"
5557
metricstorage "github.com/openstack-k8s-operators/telemetry-operator/pkg/metricstorage"
5658
monv1 "github.com/rhobs/obo-prometheus-operator/pkg/apis/monitoring/v1"
5759
obov1 "github.com/rhobs/observability-operator/pkg/apis/monitoring/v1alpha1"
@@ -79,6 +81,7 @@ func (r *MetricStorageReconciler) GetLogger(ctx context.Context) logr.Logger {
7981
//+kubebuilder:rbac:groups=monitoring.rhobs,resources=monitoringstacks,verbs=get;list;watch;create;update;patch;delete
8082
//+kubebuilder:rbac:groups=monitoring.rhobs,resources=servicemonitors,verbs=get;list;watch;create;update;patch;delete
8183
//+kubebuilder:rbac:groups=monitoring.rhobs,resources=scrapeconfigs,verbs=get;list;watch;create;update;patch;delete
84+
//+kubebuilder:rbac:groups=monitoring.rhobs,resources=prometheusrules,verbs=get;list;watch;create;update;patch;delete
8285
//+kubebuilder:rbac:groups=network.openstack.org,resources=ipsets,verbs=get;list;watch
8386
//+kubebuilder:rbac:groups=dataplane.openstack.org,resources=openstackdataplanenodesets,verbs=get;list;watch
8487
//+kubebuilder:rbac:groups=dataplane.openstack.org,resources=openstackdataplaneservices,verbs=get;list;watch
@@ -148,6 +151,9 @@ func (r *MetricStorageReconciler) Reconcile(ctx context.Context, req ctrl.Reques
148151
condition.UnknownCondition(telemetryv1.ServiceMonitorReadyCondition, condition.InitReason, telemetryv1.ServiceMonitorReadyInitMessage),
149152
condition.UnknownCondition(telemetryv1.ScrapeConfigReadyCondition, condition.InitReason, telemetryv1.ScrapeConfigReadyInitMessage),
150153
condition.UnknownCondition(telemetryv1.NodeSetReadyCondition, condition.InitReason, telemetryv1.NodeSetReadyInitMessage),
154+
condition.UnknownCondition(telemetryv1.DashboardPrometheusRuleReadyCondition, condition.InitReason, telemetryv1.DashboardPrometheusRuleReadyInitMessage),
155+
condition.UnknownCondition(telemetryv1.DashboardDatasourceReadyCondition, condition.InitReason, telemetryv1.DashboardDatasourceReadyInitMessage),
156+
condition.UnknownCondition(telemetryv1.DashboardDefinitionReadyCondition, condition.InitReason, telemetryv1.DashboardDefinitionReadyInitMessage),
151157
)
152158

153159
instance.Status.Conditions.Init(&cl)
@@ -375,6 +381,121 @@ func (r *MetricStorageReconciler) reconcileNormal(
375381
}
376382
instance.Status.Conditions.MarkTrue(telemetryv1.ScrapeConfigReadyCondition, condition.ReadyMessage)
377383

384+
if !instance.Spec.MonitoringStack.DashboardsEnabled {
385+
instance.Status.Conditions.MarkTrue(telemetryv1.DashboardPrometheusRuleReadyCondition, telemetryv1.DashboardsNotEnabledMessage)
386+
instance.Status.Conditions.MarkTrue(telemetryv1.DashboardDatasourceReadyCondition, telemetryv1.DashboardsNotEnabledMessage)
387+
instance.Status.Conditions.MarkTrue(telemetryv1.DashboardDefinitionReadyCondition, telemetryv1.DashboardsNotEnabledMessage)
388+
} else {
389+
// Deploy PrometheusRule for dashboards
390+
err = r.ensureWatches(ctx, "prometheusrules.monitoring.rhobs", &monv1.PrometheusRule{}, eventHandler)
391+
if err != nil {
392+
instance.Status.Conditions.MarkFalse(telemetryv1.DashboardPrometheusRuleReadyCondition,
393+
condition.Reason("Can't own PrometheusRule resource"),
394+
condition.SeverityError,
395+
telemetryv1.DashboardPrometheusRuleUnableToOwnMessage, err)
396+
Log.Info("Can't own PrometheusRule resource")
397+
return ctrl.Result{RequeueAfter: telemetryv1.PauseBetweenWatchAttempts}, nil
398+
}
399+
prometheusRule := &monv1.PrometheusRule{
400+
ObjectMeta: metav1.ObjectMeta{
401+
Name: instance.Name,
402+
Namespace: instance.Namespace,
403+
},
404+
}
405+
op, err = controllerutil.CreateOrPatch(ctx, r.Client, prometheusRule, func() error {
406+
ruleLabels := map[string]string{
407+
common.AppSelector: telemetryv1.DefaultServiceName,
408+
}
409+
desiredPrometheusRule := metricstorage.DashboardPrometheusRule(instance, serviceLabels, ruleLabels)
410+
desiredPrometheusRule.Spec.DeepCopyInto(&prometheusRule.Spec)
411+
prometheusRule.ObjectMeta.Labels = desiredPrometheusRule.ObjectMeta.Labels
412+
err = controllerutil.SetControllerReference(instance, prometheusRule, r.Scheme)
413+
return err
414+
})
415+
if err != nil {
416+
return ctrl.Result{}, err
417+
}
418+
if op != controllerutil.OperationResultNone {
419+
Log.Info(fmt.Sprintf("Prometheus Rules %s successfully changed - operation: %s", prometheusRule.Name, string(op)))
420+
}
421+
instance.Status.Conditions.MarkTrue(telemetryv1.DashboardPrometheusRuleReadyCondition, condition.ReadyMessage)
422+
423+
// Deploy Configmap for Console UI Datasource
424+
datasourceName := instance.Namespace + "-" + instance.Name + "-datasource"
425+
datasourceCM := &corev1.ConfigMap{
426+
ObjectMeta: metav1.ObjectMeta{
427+
Name: datasourceName,
428+
Namespace: "console-dashboards",
429+
},
430+
}
431+
dataSourceSuccess := false
432+
op, err = controllerutil.CreateOrPatch(ctx, r.Client, datasourceCM, func() error {
433+
datasourceCM.ObjectMeta.Labels = map[string]string{
434+
"console.openshift.io/dashboard-datasource": "true",
435+
}
436+
datasourceCM.Data = map[string]string{
437+
// WARNING: The lines below MUST be indented with spaces instead of tabs
438+
"dashboard-datasource.yaml": `
439+
kind: "Datasource"
440+
metadata:
441+
name: "` + datasourceName + `"
442+
spec:
443+
plugin:
444+
kind: "PrometheusDatasource"
445+
spec:
446+
direct_url: "http://prometheus-operated.` + instance.Namespace + ".svc.cluster.local:9090\"",
447+
}
448+
return nil
449+
})
450+
if err != nil {
451+
Log.Error(err, "Failed to update Console UI Datasource ConfigMap %s - operation: %s", datasourceCM.Name, string(op))
452+
instance.Status.Conditions.MarkFalse(telemetryv1.DashboardDatasourceReadyCondition,
453+
condition.Reason("Can't create Console UI Datasource ConfigMap"),
454+
condition.SeverityError,
455+
telemetryv1.DashboardDatasourceFailedMessage, err)
456+
} else {
457+
dataSourceSuccess = true
458+
instance.Status.Conditions.MarkTrue(telemetryv1.DashboardDatasourceReadyCondition, condition.ReadyMessage)
459+
}
460+
if op != controllerutil.OperationResultNone {
461+
Log.Info(fmt.Sprintf("Console UI Datasource ConfigMap %s successfully changed - operation: %s", datasourceCM.Name, string(op)))
462+
}
463+
464+
// Deploy ConfigMaps for dashboards
465+
// NOTE: Dashboards installed without the custom datasource will default to the openshift-monitoring prometheus causing unexpected results
466+
if dataSourceSuccess {
467+
dashboardCMs := map[string]*corev1.ConfigMap{
468+
"grafana-dashboard-openstack-cloud": dashboards.OpenstackCloud(datasourceName),
469+
"grafana-dashboard-openstack-node": dashboards.OpenstackNode(datasourceName),
470+
}
471+
472+
for dashboardName, desiredCM := range dashboardCMs {
473+
dashboardCM := &corev1.ConfigMap{
474+
ObjectMeta: metav1.ObjectMeta{
475+
Name: dashboardName,
476+
Namespace: "openshift-config-managed",
477+
},
478+
}
479+
op, err = controllerutil.CreateOrPatch(ctx, r.Client, dashboardCM, func() error {
480+
dashboardCM.ObjectMeta.Labels = desiredCM.ObjectMeta.Labels
481+
dashboardCM.Data = desiredCM.Data
482+
return nil
483+
})
484+
if err != nil {
485+
Log.Error(err, "Failed to update Dashboard ConfigMap %s - operation: %s", dashboardCM.Name, string(op))
486+
instance.Status.Conditions.MarkFalse(telemetryv1.DashboardDefinitionReadyCondition,
487+
condition.Reason("Can't create Console UI Dashboard ConfigMap"),
488+
condition.SeverityError,
489+
telemetryv1.DashboardDefinitionFailedMessage, err)
490+
} else {
491+
instance.Status.Conditions.MarkTrue(telemetryv1.DashboardDefinitionReadyCondition, condition.ReadyMessage)
492+
}
493+
if op != controllerutil.OperationResultNone {
494+
Log.Info(fmt.Sprintf("Dashboard ConfigMap %s successfully changed - operation: %s", dashboardCM.Name, string(op)))
495+
}
496+
}
497+
}
498+
}
378499
Log.Info("Reconciled Service successfully")
379500
return ctrl.Result{}, nil
380501
}
@@ -547,6 +668,7 @@ func isValidDomain(domain string) bool {
547668
func (r *MetricStorageReconciler) SetupWithManager(mgr ctrl.Manager) error {
548669
control, err := ctrl.NewControllerManagedBy(mgr).
549670
For(&telemetryv1.MetricStorage{}).
671+
Owns(&monv1.PrometheusRule{}).
550672
Build(r)
551673
r.Controller = control
552674
return err

hack/configure_local_webhook.sh

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ CRC_IP=${CRC_IP:-$(/sbin/ip -o -4 addr list crc | awk '{print $4}' | cut -d/ -f1
77
FIREWALL_ZONE=${FIREWALL_ZONE:-"libvirt"}
88

99
#Open 9443
10-
sudo firewall-cmd --zone=${FIREWALL_ZONE} --add-port=9443/tcp
11-
sudo firewall-cmd --runtime-to-permanent
10+
if systemctl is-enabled firewalld; then
11+
sudo firewall-cmd --zone=${FIREWALL_ZONE} --add-port=9443/tcp
12+
sudo firewall-cmd --runtime-to-permanent
13+
fi
1214

1315
# Generate the certs and the ca bundle
1416
if [ "$SKIP_CERT" = false ] ; then

0 commit comments

Comments
 (0)