Skip to content

Commit 3758eb7

Browse files
feat: enable optional ServiceMonitor creation for Backstage CR (#1374)
* feat: enable optional ServiceMonitor creation for Backstage CR Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * Regenerate bundle/installer manifests Co-authored-by: Fortune-Ndlovu <Fortune-Ndlovu@users.noreply.github.com> * adding the new spec.monitoring field to the CRD Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * Regenerate bundle/installer manifests Co-authored-by: Fortune-Ndlovu <Fortune-Ndlovu@users.noreply.github.com> * Updated the CRD (config/crd/bases/rhdh.redhat.com_backstages.yaml) via make manifests. Implemented applyServiceMonitor logic in monitor.go. Added RBAC for ServiceMonitor and regenerated manager-role. Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * Regenerate bundle/installer manifests Co-authored-by: Fortune-Ndlovu <Fortune-Ndlovu@users.noreply.github.com> * correct port and path endpoints Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * test monitoringv1 Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * test: add minimal ServiceMonitor CRD for envtest integration tests Envtest does not include the Prometheus Operator CRDs by default, so tests that reconcile ServiceMonitor resources failed with for kind ServiceMonitor in version monitoring.coreos.com/v1. This commit adds a minimal CRD under to make envtest aware of the resource type during integration tests. This avoids pulling the full Prometheus Operator CRDs while keeping tests lightweight and self-contained. Fixes: integration test failures in BackstageReconciler when monitoring.enabled=true. Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * Apply ServiceMonitor before Backstage model initialization, this way even if InitObjects() fails (like our deployment.yaml missing case), the ServiceMonitor still gets created. Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * The CRD is confirmed installed, so always allow ServiceMonitor creation Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * debugs Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * Regenerate bundle/installer manifests Co-authored-by: Fortune-Ndlovu <Fortune-Ndlovu@users.noreply.github.com> * Switching from server-side apply (client.Apply) to a safer (controllerutil.CreateOrUpdate) do fix the error 'invalid object type: /, kind='' because client.Apply triggers a server-sideapply (ssa), which only works reliably for build-in K8s resouces or CRDs that fully support SSA. ServiceMonitor is a CRD from the Prometheus OPerator its openapi schema does not fully support ssa so the k8s api server cant determine its type it returns an empty kind hence error invalid object type Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * Update: feat(operator): add optional ServiceMonitor support for Backstage CR - Introduce in Backstage CRD - Create/update ServiceMonitor only if Prometheus Operator CRD exists - Gracefully skip with warning on vanilla Kubernetes clusters - Delete ServiceMonitor when monitoring is disabled - Idempotent creation with owner references for cleanup Includes: - CRD schema update for monitoring.enabled - RBAC permissions for monitoring.coreos.com/servicemonitors - ServiceMonitor creation logic in controller Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * Updated main.go to register apiextensions.k8s.io/v1 types in the manager scheme so CRD lookups can be decoded properly Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * Add RBAC to allow checking ServiceMonitor CRD (apiextensions.k8s.io) and persist it Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * Regenerate bundle/installer manifests Co-authored-by: Fortune-Ndlovu <Fortune-Ndlovu@users.noreply.github.com> * update cache Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * Regenerate bundle/installer manifests Co-authored-by: Fortune-Ndlovu <Fortune-Ndlovu@users.noreply.github.com> * fix scheme registration Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * add tests Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * update Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * fixup Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * fixup Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * fix test missing label Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * fix: remove duplicate API compatibility test - Remove duplicate test from config-refresh_test.go - Keep the dedicated test in cr-compatibility_test.go (from main) - Clean up unused imports (bsv1alpha3, metav1) - Fixes test duplication causing CI failures * update Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * fix: restore ServiceMonitor scheme registration in integration tests - Add back monitoringv1 import and AddToScheme() registration - Add back external CRD directory to load ServiceMonitor CRDs - Fix cr-compatibility test to use deployment spec validation instead of pod readiness - This allows controller to properly clean up ServiceMonitors even when monitoring is disabled Fixes the 'no kind is registered for the type v1.ServiceMonitor' error that was causing 12 integration test failures when the controller tried to delete ServiceMonitors. * add: server side apply logic to Service Monitor to use the same resource management patterns Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * refactor: use direct ServiceMonitor creation instead of CRD pre-check. Replace explicit CRD existence check with direct creation and error handling.Reduces API calls and follows more idiomatic Kubernetes controller patterns. Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * resolving dependencies and tests Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * return true Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * update test Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * clean up error parcing logic Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * removing redundent code Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * fix test by removing TypeMeta assertions Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * remove redundent log Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * remove kubebuilder RBAC annotation from backstage_controller.go and regenerate bundle manifests Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * Regenerate bundle/installer manifests Co-authored-by: Fortune-Ndlovu <Fortune-Ndlovu@users.noreply.github.com> * add typemeta and singleline patchoptions Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> * generate consistent naming to align with other objects Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> --------- Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Fortune-Ndlovu <Fortune-Ndlovu@users.noreply.github.com>
1 parent ccbfc04 commit 3758eb7

19 files changed

Lines changed: 547 additions & 7 deletions

api/v1alpha4/backstage_types.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ type BackstageSpec struct {
2929
// Configuration for database access. Optional.
3030
Database *Database `json:"database,omitempty"`
3131

32+
// Monitoring config to enable ServiceMonitor for metrics
33+
// +optional
34+
// +kubebuilder:default={enabled:false}
35+
Monitoring Monitoring `json:"monitoring,omitempty"`
36+
3237
// Valid fragment of Deployment to be merged with default/raw configuration.
3338
// Set the Deployment's metadata and|or spec fields you want to override or add.
3439
// Optional.
@@ -68,6 +73,13 @@ type Database struct {
6873
AuthSecretName string `json:"authSecretName,omitempty"`
6974
}
7075

76+
type Monitoring struct {
77+
// Enable ServiceMonitor for Prometheus scraping
78+
// +optional
79+
// +kubebuilder:default=false
80+
Enabled bool `json:"enabled,omitempty"`
81+
}
82+
7183
type Application struct {
7284
// References to existing app-configs ConfigMap objects, that will be mounted as files in the specified mount path.
7385
// Each element can be a reference to any ConfigMap or Secret,
@@ -329,3 +341,10 @@ func (s *BackstageSpec) IsRouteEnabled() bool {
329341
func (s *BackstageSpec) IsAuthSecretSpecified() bool {
330342
return s.Database != nil && s.Database.AuthSecretName != ""
331343
}
344+
345+
// IsMonitoringEnabled checks if monitoring is explicitly enabled in the BackstageSpec.
346+
// Returns false if the Monitoring field is nil (not configured) or explicitly disabled.
347+
// Returns true only when spec.monitoring.enabled is set to true in the CR
348+
func (s *BackstageSpec) IsMonitoringEnabled() bool {
349+
return s.Monitoring.Enabled
350+
}

api/v1alpha4/zz_generated.deepcopy.go

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bundle/backstage.io/manifests/backstage-operator.clusterserviceversion.yaml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ metadata:
4545
}
4646
}
4747
]
48-
createdAt: "2025-07-31T18:53:34Z"
48+
createdAt: "2025-08-05T13:32:45Z"
4949
description: Backstage Operator
5050
operators.operatorframework.io/builder: operator-sdk-v1.37.0
5151
operators.operatorframework.io/project_layout: go.kubebuilder.io/v4
@@ -139,6 +139,18 @@ spec:
139139
- ingresses
140140
verbs:
141141
- get
142+
- apiGroups:
143+
- monitoring.coreos.com
144+
resources:
145+
- servicemonitors
146+
verbs:
147+
- create
148+
- delete
149+
- get
150+
- list
151+
- patch
152+
- update
153+
- watch
142154
- apiGroups:
143155
- rhdh.redhat.com
144156
resources:

bundle/backstage.io/manifests/rhdh.redhat.com_backstages.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1512,6 +1512,16 @@ spec:
15121512
Optional.
15131513
x-kubernetes-preserve-unknown-fields: true
15141514
type: object
1515+
monitoring:
1516+
default:
1517+
enabled: false
1518+
description: Monitoring config to enable ServiceMonitor for metrics
1519+
properties:
1520+
enabled:
1521+
default: false
1522+
description: Enable ServiceMonitor for Prometheus scraping
1523+
type: boolean
1524+
type: object
15151525
rawRuntimeConfig:
15161526
description: Raw Runtime RuntimeObjects configuration. For Advanced
15171527
scenarios.

bundle/rhdh/manifests/backstage-operator.clusterserviceversion.yaml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ metadata:
4949
categories: Developer Tools
5050
certified: "true"
5151
containerImage: registry.redhat.io/rhdh/rhdh-rhel9-operator:1.8
52-
createdAt: "2025-07-31T18:53:36Z"
52+
createdAt: "2025-08-05T13:32:47Z"
5353
description: Red Hat Developer Hub is a Red Hat supported version of Backstage.
5454
It comes with pre-built plug-ins and configuration settings, supports use of
5555
an external database, and can help streamline the process of setting up a self-managed
@@ -179,6 +179,18 @@ spec:
179179
- ingresses
180180
verbs:
181181
- get
182+
- apiGroups:
183+
- monitoring.coreos.com
184+
resources:
185+
- servicemonitors
186+
verbs:
187+
- create
188+
- delete
189+
- get
190+
- list
191+
- patch
192+
- update
193+
- watch
182194
- apiGroups:
183195
- rhdh.redhat.com
184196
resources:

bundle/rhdh/manifests/rhdh.redhat.com_backstages.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1512,6 +1512,16 @@ spec:
15121512
Optional.
15131513
x-kubernetes-preserve-unknown-fields: true
15141514
type: object
1515+
monitoring:
1516+
default:
1517+
enabled: false
1518+
description: Monitoring config to enable ServiceMonitor for metrics
1519+
properties:
1520+
enabled:
1521+
default: false
1522+
description: Enable ServiceMonitor for Prometheus scraping
1523+
type: boolean
1524+
type: object
15151525
rawRuntimeConfig:
15161526
description: Raw Runtime RuntimeObjects configuration. For Advanced
15171527
scenarios.

cmd/main.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ import (
1919
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
2020
"sigs.k8s.io/controller-runtime/pkg/webhook"
2121

22+
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
2223
bsv1 "github.com/redhat-developer/rhdh-operator/api/v1alpha4"
24+
2325
"github.com/redhat-developer/rhdh-operator/internal/controller"
2426

2527
openshift "github.com/openshift/api/route/v1"
@@ -37,6 +39,8 @@ func init() {
3739
utilruntime.Must(bsv1.AddToScheme(scheme))
3840

3941
utilruntime.Must(openshift.Install(scheme))
42+
43+
utilruntime.Must(monitoringv1.AddToScheme(scheme))
4044
//+kubebuilder:scaffold:scheme
4145
}
4246

config/crd/bases/rhdh.redhat.com_backstages.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1512,6 +1512,16 @@ spec:
15121512
Optional.
15131513
x-kubernetes-preserve-unknown-fields: true
15141514
type: object
1515+
monitoring:
1516+
default:
1517+
enabled: false
1518+
description: Monitoring config to enable ServiceMonitor for metrics
1519+
properties:
1520+
enabled:
1521+
default: false
1522+
description: Enable ServiceMonitor for Prometheus scraping
1523+
type: boolean
1524+
type: object
15151525
rawRuntimeConfig:
15161526
description: Raw Runtime RuntimeObjects configuration. For Advanced
15171527
scenarios.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
apiVersion: apiextensions.k8s.io/v1
2+
kind: CustomResourceDefinition
3+
metadata:
4+
name: servicemonitors.monitoring.coreos.com
5+
spec:
6+
group: monitoring.coreos.com
7+
scope: Namespaced
8+
names:
9+
plural: servicemonitors
10+
singular: servicemonitor
11+
kind: ServiceMonitor
12+
versions:
13+
- name: v1
14+
served: true
15+
storage: true
16+
schema:
17+
openAPIV3Schema:
18+
type: object

config/rbac/role.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,18 @@ rules:
4646
- ingresses
4747
verbs:
4848
- get
49+
- apiGroups:
50+
- monitoring.coreos.com
51+
resources:
52+
- servicemonitors
53+
verbs:
54+
- create
55+
- delete
56+
- get
57+
- list
58+
- patch
59+
- update
60+
- watch
4961
- apiGroups:
5062
- rhdh.redhat.com
5163
resources:

0 commit comments

Comments
 (0)