From cfb6a67f0947af4518cc39c16e55821a0ebf418e Mon Sep 17 00:00:00 2001 From: Jaromir Wysoglad Date: Thu, 16 Jul 2026 08:59:15 -0400 Subject: [PATCH] Make polling.yaml dynamic based on enabled services The ceilometer central agent's polling.yaml will change dynamically and include Designate, Octavia or Manila polling configuration if these services are enabled. The mechanism is watching the KeystoneEndpoint CRs to determine whether these services are enabled. This means we don't need to add any new watches (like watching the Octavia CR) and we don't need any new dependencies (like the octavia-operator). This works very similar to how swift polling config worked until now. Also ceilometer would already restart on each new KeystoneEndpoint, so there isn't any additional reconciling / pod restarts compared to the previous behavior. Generated-By: Claude-Code claude-opus-4-6 --- internal/controller/ceilometer_controller.go | 46 +++++++++++++------ .../ceilometercentral/config/polling.yaml.j2 | 9 ++++ test/kuttl/tests/ceilometer/04-assert.yaml | 10 ++++ .../ceilometer/04-conditional-polling.yaml | 33 +++++++++++++ 4 files changed, 85 insertions(+), 13 deletions(-) create mode 100644 test/kuttl/tests/ceilometer/04-assert.yaml create mode 100644 test/kuttl/tests/ceilometer/04-conditional-polling.yaml diff --git a/internal/controller/ceilometer_controller.go b/internal/controller/ceilometer_controller.go index 0e418f3ab..9bfcfb259 100644 --- a/internal/controller/ceilometer_controller.go +++ b/internal/controller/ceilometer_controller.go @@ -1309,7 +1309,10 @@ func (r *CeilometerReconciler) generateServiceConfig( "TransportURL": string(transportURLSecret.Data["transport_url"]), "CeilometerPassword": string(ceilometerPasswordSecret.Data["CeilometerPassword"]), "TLS": false, // Default to false. Change to true later if TLS enabled - "SwiftRole": false, // + "SwiftRole": false, + "ManilaEnabled": false, + "DesignateEnabled": false, + "OctaviaEnabled": false, "Timeout": instance.Spec.APITimeout, "Region": keystoneAPI.GetRegion(), } @@ -1355,6 +1358,17 @@ func (r *CeilometerReconciler) generateServiceConfig( templateParameters["SwiftRole"] = true } + // If Manila/Designate/Octavia endpoints exist, add their meters to polling + if r.endpointExists(ctx, h, "manilav2", instance.Namespace, h.GetLogger()) { + templateParameters["ManilaEnabled"] = true + } + if r.endpointExists(ctx, h, "designate", instance.Namespace, h.GetLogger()) { + templateParameters["DesignateEnabled"] = true + } + if r.endpointExists(ctx, h, "octavia", instance.Namespace, h.GetLogger()) { + templateParameters["OctaviaEnabled"] = true + } + // Add NotificationsURL if configured // Always get the separate notification secret since we always create separate TransportURLs if instance.Status.NotificationsURLSecret != nil && *instance.Status.NotificationsURLSecret != "" { @@ -1831,17 +1845,6 @@ func (r *CeilometerReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Ma return nil } - // Reconcile every time a keystoneendpoint is modified - keystoneEndpointsWatchFn := func(_ context.Context, o client.Object) []reconcile.Request { - result := []reconcile.Request{} - name := client.ObjectKey{ - Namespace: o.GetNamespace(), - Name: ceilometer.ServiceName, - } - result = append(result, reconcile.Request{NamespacedName: name}) - return result - } - galeraWatchFn := func(_ context.Context, o client.Object) []reconcile.Request { result := []reconcile.Request{} @@ -2017,7 +2020,7 @@ func (r *CeilometerReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Ma ). Watches( &keystonev1.KeystoneEndpoint{}, - handler.EnqueueRequestsFromMapFunc(keystoneEndpointsWatchFn), + handler.EnqueueRequestsFromMapFunc(r.findObjectForSrc), ). Watches( &mariadbv1.Galera{}, @@ -2097,6 +2100,23 @@ func (r *CeilometerReconciler) findObjectForSrc(ctx context.Context, src client. return requests } +func (r *CeilometerReconciler) endpointExists( + ctx context.Context, + h *helper.Helper, + endpointName string, + namespace string, + log logr.Logger, +) bool { + _, err := keystonev1.GetKeystoneEndpointWithName(ctx, h, endpointName, namespace) + if err != nil { + if !k8s_errors.IsNotFound(err) { + log.Error(err, fmt.Sprintf("Failed to check for KeystoneEndpoint/%s, assuming not present", endpointName)) + } + return false + } + return true +} + func (r CeilometerReconciler) roleExists( ctx context.Context, helper *helper.Helper, diff --git a/templates/ceilometercentral/config/polling.yaml.j2 b/templates/ceilometercentral/config/polling.yaml.j2 index d40a067f7..90b2b2321 100644 --- a/templates/ceilometercentral/config/polling.yaml.j2 +++ b/templates/ceilometercentral/config/polling.yaml.j2 @@ -9,3 +9,12 @@ sources: {{- if .SwiftRole }} - storage.* {{- end }} +{{- if .ManilaEnabled }} + - manila.* +{{- end }} +{{- if .DesignateEnabled }} + - dns.* +{{- end }} +{{- if .OctaviaEnabled }} + - loadbalancer.* +{{- end }} diff --git a/test/kuttl/tests/ceilometer/04-assert.yaml b/test/kuttl/tests/ceilometer/04-assert.yaml new file mode 100644 index 000000000..5548db6ef --- /dev/null +++ b/test/kuttl/tests/ceilometer/04-assert.yaml @@ -0,0 +1,10 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 300 +commands: +- script: > + oc get secret ceilometer-config-data -n $NAMESPACE -o jsonpath='{.data.polling\.yaml\.j2}' | base64 -d | grep 'manila\.\*' +- script: > + oc get secret ceilometer-config-data -n $NAMESPACE -o jsonpath='{.data.polling\.yaml\.j2}' | base64 -d | grep 'dns\.\*' +- script: > + oc get secret ceilometer-config-data -n $NAMESPACE -o jsonpath='{.data.polling\.yaml\.j2}' | base64 -d | grep 'loadbalancer\.\*' diff --git a/test/kuttl/tests/ceilometer/04-conditional-polling.yaml b/test/kuttl/tests/ceilometer/04-conditional-polling.yaml new file mode 100644 index 000000000..88fe478f4 --- /dev/null +++ b/test/kuttl/tests/ceilometer/04-conditional-polling.yaml @@ -0,0 +1,33 @@ +--- +apiVersion: keystone.openstack.org/v1beta1 +kind: KeystoneEndpoint +metadata: + name: manilav2 + labels: + service: manilav2 +spec: + serviceName: manilav2 + endpoints: + internal: http://manila-internal.openstack.svc:8786/v2 +--- +apiVersion: keystone.openstack.org/v1beta1 +kind: KeystoneEndpoint +metadata: + name: designate + labels: + service: designate +spec: + serviceName: designate + endpoints: + internal: http://designate-internal.openstack.svc:9001 +--- +apiVersion: keystone.openstack.org/v1beta1 +kind: KeystoneEndpoint +metadata: + name: octavia + labels: + service: octavia +spec: + serviceName: octavia + endpoints: + internal: http://octavia-internal.openstack.svc:9876