Skip to content

Commit 2d44e7f

Browse files
Cleanup: provide supported steps, syncers, ... over same file pattern [skip ci]
1 parent dca05ba commit 2d44e7f

File tree

12 files changed

+208
-137
lines changed

12 files changed

+208
-137
lines changed

cmd/main.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -456,9 +456,8 @@ func main() {
456456
}
457457
if slices.Contains(config.EnabledControllers, "kpis-controller") {
458458
if err := (&kpis.Controller{
459-
Client: multiclusterClient,
460-
SupportedKPIsByImpl: kpis.SupportedKPIsByImpl,
461-
OperatorName: config.Operator,
459+
Client: multiclusterClient,
460+
OperatorName: config.Operator,
462461
}).SetupWithManager(mgr, multiclusterClient); err != nil {
463462
setupLog.Error(err, "unable to create controller", "controller", "KPIController")
464463
os.Exit(1)

internal/knowledge/datasources/openstack/controller.go

Lines changed: 7 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,6 @@ import (
1111

1212
"github.com/cobaltcore-dev/cortex/api/v1alpha1"
1313
"github.com/cobaltcore-dev/cortex/internal/knowledge/datasources"
14-
"github.com/cobaltcore-dev/cortex/internal/knowledge/datasources/openstack/cinder"
15-
"github.com/cobaltcore-dev/cortex/internal/knowledge/datasources/openstack/identity"
16-
"github.com/cobaltcore-dev/cortex/internal/knowledge/datasources/openstack/limes"
17-
"github.com/cobaltcore-dev/cortex/internal/knowledge/datasources/openstack/manila"
18-
"github.com/cobaltcore-dev/cortex/internal/knowledge/datasources/openstack/nova"
19-
"github.com/cobaltcore-dev/cortex/internal/knowledge/datasources/openstack/placement"
2014
"github.com/cobaltcore-dev/cortex/pkg/conf"
2115
"github.com/cobaltcore-dev/cortex/pkg/db"
2216
"github.com/cobaltcore-dev/cortex/pkg/keystone"
@@ -129,51 +123,13 @@ func (r *OpenStackDatasourceReconciler) Reconcile(ctx context.Context, req ctrl.
129123
return ctrl.Result{}, err
130124
}
131125

132-
var syncer Syncer
133-
switch datasource.Spec.OpenStack.Type {
134-
case v1alpha1.OpenStackDatasourceTypeNova:
135-
syncer = &nova.NovaSyncer{
136-
DB: *authenticatedDB,
137-
Mon: r.Monitor,
138-
Conf: datasource.Spec.OpenStack.Nova,
139-
API: nova.NewNovaAPI(r.Monitor, authenticatedKeystone, datasource.Spec.OpenStack.Nova),
140-
}
141-
case v1alpha1.OpenStackDatasourceTypeManila:
142-
syncer = &manila.ManilaSyncer{
143-
DB: *authenticatedDB,
144-
Mon: r.Monitor,
145-
Conf: datasource.Spec.OpenStack.Manila,
146-
API: manila.NewManilaAPI(r.Monitor, authenticatedKeystone, datasource.Spec.OpenStack.Manila),
147-
}
148-
case v1alpha1.OpenStackDatasourceTypePlacement:
149-
syncer = &placement.PlacementSyncer{
150-
DB: *authenticatedDB,
151-
Mon: r.Monitor,
152-
Conf: datasource.Spec.OpenStack.Placement,
153-
API: placement.NewPlacementAPI(r.Monitor, authenticatedKeystone, datasource.Spec.OpenStack.Placement),
154-
}
155-
case v1alpha1.OpenStackDatasourceTypeIdentity:
156-
syncer = &identity.IdentitySyncer{
157-
DB: *authenticatedDB,
158-
Mon: r.Monitor,
159-
Conf: datasource.Spec.OpenStack.Identity,
160-
API: identity.NewIdentityAPI(r.Monitor, authenticatedKeystone, datasource.Spec.OpenStack.Identity),
161-
}
162-
case v1alpha1.OpenStackDatasourceTypeLimes:
163-
syncer = &limes.LimesSyncer{
164-
DB: *authenticatedDB,
165-
Mon: r.Monitor,
166-
Conf: datasource.Spec.OpenStack.Limes,
167-
API: limes.NewLimesAPI(r.Monitor, authenticatedKeystone, datasource.Spec.OpenStack.Limes),
168-
}
169-
case v1alpha1.OpenStackDatasourceTypeCinder:
170-
syncer = &cinder.CinderSyncer{
171-
DB: *authenticatedDB,
172-
Mon: r.Monitor,
173-
Conf: datasource.Spec.OpenStack.Cinder,
174-
API: cinder.NewCinderAPI(r.Monitor, authenticatedKeystone, datasource.Spec.OpenStack.Cinder),
175-
}
176-
default:
126+
syncer, err := getSupportedSyncer(
127+
*datasource,
128+
authenticatedDB,
129+
authenticatedKeystone,
130+
r.Monitor,
131+
)
132+
if err != nil {
177133
log.Info("skipping datasource, unsupported openstack datasource type", "type", datasource.Spec.OpenStack.Type)
178134
meta.SetStatusCondition(&datasource.Status.Conditions, metav1.Condition{
179135
Type: v1alpha1.DatasourceConditionError,
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Copyright 2025 SAP SE
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package openstack
5+
6+
import (
7+
"errors"
8+
9+
"github.com/cobaltcore-dev/cortex/api/v1alpha1"
10+
"github.com/cobaltcore-dev/cortex/internal/knowledge/datasources"
11+
"github.com/cobaltcore-dev/cortex/internal/knowledge/datasources/openstack/cinder"
12+
"github.com/cobaltcore-dev/cortex/internal/knowledge/datasources/openstack/identity"
13+
"github.com/cobaltcore-dev/cortex/internal/knowledge/datasources/openstack/limes"
14+
"github.com/cobaltcore-dev/cortex/internal/knowledge/datasources/openstack/manila"
15+
"github.com/cobaltcore-dev/cortex/internal/knowledge/datasources/openstack/nova"
16+
"github.com/cobaltcore-dev/cortex/internal/knowledge/datasources/openstack/placement"
17+
"github.com/cobaltcore-dev/cortex/pkg/db"
18+
"github.com/cobaltcore-dev/cortex/pkg/keystone"
19+
)
20+
21+
// Get the supported syncer for the given datasource.
22+
func getSupportedSyncer(
23+
datasource v1alpha1.Datasource,
24+
authenticatedDB *db.DB,
25+
authenticatedKeystone keystone.KeystoneAPI,
26+
monitor datasources.Monitor,
27+
) (Syncer, error) {
28+
29+
switch datasource.Spec.OpenStack.Type {
30+
case v1alpha1.OpenStackDatasourceTypeNova:
31+
return &nova.NovaSyncer{
32+
DB: *authenticatedDB,
33+
Mon: monitor,
34+
Conf: datasource.Spec.OpenStack.Nova,
35+
API: nova.NewNovaAPI(monitor, authenticatedKeystone, datasource.Spec.OpenStack.Nova),
36+
}, nil
37+
case v1alpha1.OpenStackDatasourceTypeManila:
38+
return &manila.ManilaSyncer{
39+
DB: *authenticatedDB,
40+
Mon: monitor,
41+
Conf: datasource.Spec.OpenStack.Manila,
42+
API: manila.NewManilaAPI(monitor, authenticatedKeystone, datasource.Spec.OpenStack.Manila),
43+
}, nil
44+
case v1alpha1.OpenStackDatasourceTypePlacement:
45+
return &placement.PlacementSyncer{
46+
DB: *authenticatedDB,
47+
Mon: monitor,
48+
Conf: datasource.Spec.OpenStack.Placement,
49+
API: placement.NewPlacementAPI(monitor, authenticatedKeystone, datasource.Spec.OpenStack.Placement),
50+
}, nil
51+
case v1alpha1.OpenStackDatasourceTypeIdentity:
52+
return &identity.IdentitySyncer{
53+
DB: *authenticatedDB,
54+
Mon: monitor,
55+
Conf: datasource.Spec.OpenStack.Identity,
56+
API: identity.NewIdentityAPI(monitor, authenticatedKeystone, datasource.Spec.OpenStack.Identity),
57+
}, nil
58+
case v1alpha1.OpenStackDatasourceTypeLimes:
59+
return &limes.LimesSyncer{
60+
DB: *authenticatedDB,
61+
Mon: monitor,
62+
Conf: datasource.Spec.OpenStack.Limes,
63+
API: limes.NewLimesAPI(monitor, authenticatedKeystone, datasource.Spec.OpenStack.Limes),
64+
}, nil
65+
case v1alpha1.OpenStackDatasourceTypeCinder:
66+
return &cinder.CinderSyncer{
67+
DB: *authenticatedDB,
68+
Mon: monitor,
69+
Conf: datasource.Spec.OpenStack.Cinder,
70+
API: cinder.NewCinderAPI(monitor, authenticatedKeystone, datasource.Spec.OpenStack.Cinder),
71+
}, nil
72+
default:
73+
return nil, errors.New("unsupported openstack datasource type")
74+
}
75+
}

internal/knowledge/datasources/prometheus/controller.go

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -58,21 +58,7 @@ func (r *PrometheusDatasourceReconciler) Reconcile(ctx context.Context, req ctrl
5858
return ctrl.Result{RequeueAfter: time.Until(datasource.Status.NextSyncTime.Time)}, nil
5959
}
6060

61-
newSyncerFunc, ok := map[string]func(
62-
ds v1alpha1.Datasource,
63-
authenticatedDB *db.DB,
64-
authenticatedHTTP *http.Client,
65-
prometheusURL string,
66-
monitor datasources.Monitor,
67-
) typedSyncer{
68-
"vrops_host_metric": newTypedSyncer[VROpsHostMetric],
69-
"vrops_vm_metric": newTypedSyncer[VROpsVMMetric],
70-
"node_exporter_metric": newTypedSyncer[NodeExporterMetric],
71-
"netapp_aggregate_labels_metric": newTypedSyncer[NetAppAggregateLabelsMetric],
72-
"netapp_node_metric": newTypedSyncer[NetAppNodeMetric],
73-
"netapp_volume_aggregate_labels_metric": newTypedSyncer[NetAppVolumeAggrLabelsMetric],
74-
"kvm_libvirt_domain_metric": newTypedSyncer[KVMDomainMetric],
75-
}[datasource.Spec.Prometheus.Type]
61+
newSyncerFunc, ok := supportedMetricSyncers[datasource.Spec.Prometheus.Type]
7662
if !ok {
7763
log.Info("skipping datasource, unsupported metric type", "metricType", datasource.Spec.Prometheus.Type)
7864
meta.SetStatusCondition(&datasource.Status.Conditions, metav1.Condition{
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2025 SAP SE
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package prometheus
5+
6+
import (
7+
"net/http"
8+
9+
"github.com/cobaltcore-dev/cortex/api/v1alpha1"
10+
"github.com/cobaltcore-dev/cortex/internal/knowledge/datasources"
11+
"github.com/cobaltcore-dev/cortex/pkg/db"
12+
)
13+
14+
// All supported Prometheus metric syncers.
15+
var supportedMetricSyncers = map[string]func(
16+
ds v1alpha1.Datasource,
17+
authenticatedDB *db.DB,
18+
authenticatedHTTP *http.Client,
19+
prometheusURL string,
20+
monitor datasources.Monitor,
21+
) typedSyncer{
22+
"vrops_host_metric": newTypedSyncer[VROpsHostMetric],
23+
"vrops_vm_metric": newTypedSyncer[VROpsVMMetric],
24+
"node_exporter_metric": newTypedSyncer[NodeExporterMetric],
25+
"netapp_aggregate_labels_metric": newTypedSyncer[NetAppAggregateLabelsMetric],
26+
"netapp_node_metric": newTypedSyncer[NetAppNodeMetric],
27+
"netapp_volume_aggregate_labels_metric": newTypedSyncer[NetAppVolumeAggrLabelsMetric],
28+
"kvm_libvirt_domain_metric": newTypedSyncer[KVMDomainMetric],
29+
}

internal/knowledge/extractor/controller.go

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,6 @@ import (
99

1010
"github.com/cobaltcore-dev/cortex/api/v1alpha1"
1111

12-
"github.com/cobaltcore-dev/cortex/internal/knowledge/extractor/plugins"
13-
"github.com/cobaltcore-dev/cortex/internal/knowledge/extractor/plugins/kvm"
14-
"github.com/cobaltcore-dev/cortex/internal/knowledge/extractor/plugins/netapp"
15-
"github.com/cobaltcore-dev/cortex/internal/knowledge/extractor/plugins/sap"
16-
"github.com/cobaltcore-dev/cortex/internal/knowledge/extractor/plugins/shared"
17-
"github.com/cobaltcore-dev/cortex/internal/knowledge/extractor/plugins/vmware"
1812
"github.com/cobaltcore-dev/cortex/pkg/conf"
1913
"github.com/cobaltcore-dev/cortex/pkg/db"
2014
"github.com/cobaltcore-dev/cortex/pkg/multicluster"
@@ -59,26 +53,7 @@ func (r *KnowledgeReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
5953
return ctrl.Result{RequeueAfter: time.Until(lastExtracted.Add(recency))}, nil
6054
}
6155

62-
extractor, ok := map[string]plugins.FeatureExtractor{
63-
// VMware-specific extractors
64-
"vrops_hostsystem_resolver": &vmware.VROpsHostsystemResolver{},
65-
"vrops_project_noisiness_extractor": &vmware.VROpsProjectNoisinessExtractor{},
66-
"vrops_hostsystem_contention_long_term_extractor": &vmware.VROpsHostsystemContentionLongTermExtractor{},
67-
"vrops_hostsystem_contention_short_term_extractor": &vmware.VROpsHostsystemContentionShortTermExtractor{},
68-
// KVM-specific extractors
69-
"kvm_libvirt_domain_cpu_steal_pct_extractor": &kvm.LibvirtDomainCPUStealPctExtractor{},
70-
// NetApp-specific extractors
71-
"netapp_storage_pool_cpu_usage_extractor": &netapp.StoragePoolCPUUsageExtractor{},
72-
// Shared extractors
73-
"host_utilization_extractor": &shared.HostUtilizationExtractor{},
74-
"host_capabilities_extractor": &shared.HostCapabilitiesExtractor{},
75-
"vm_host_residency_extractor": &shared.VMHostResidencyExtractor{},
76-
"vm_life_span_histogram_extractor": &shared.VMLifeSpanHistogramExtractor{},
77-
"host_az_extractor": &shared.HostAZExtractor{},
78-
"host_pinned_projects_extractor": &shared.HostPinnedProjectsExtractor{},
79-
// SAP-specific extractors
80-
"sap_host_details_extractor": &sap.HostDetailsExtractor{},
81-
}[knowledge.Spec.Extractor.Name]
56+
extractor, ok := supportedExtractors[knowledge.Spec.Extractor.Name]
8257
if !ok {
8358
log.Info("skipping knowledge extraction, unsupported extractor", "name", knowledge.Spec.Extractor.Name)
8459
meta.SetStatusCondition(&knowledge.Status.Conditions, metav1.Condition{
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2025 SAP SE
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package extractor
5+
6+
import (
7+
"github.com/cobaltcore-dev/cortex/internal/knowledge/extractor/plugins"
8+
"github.com/cobaltcore-dev/cortex/internal/knowledge/extractor/plugins/kvm"
9+
"github.com/cobaltcore-dev/cortex/internal/knowledge/extractor/plugins/netapp"
10+
"github.com/cobaltcore-dev/cortex/internal/knowledge/extractor/plugins/sap"
11+
"github.com/cobaltcore-dev/cortex/internal/knowledge/extractor/plugins/shared"
12+
"github.com/cobaltcore-dev/cortex/internal/knowledge/extractor/plugins/vmware"
13+
)
14+
15+
// All supported feature extractors.
16+
var supportedExtractors = map[string]plugins.FeatureExtractor{
17+
// VMware-specific extractors
18+
"vrops_hostsystem_resolver": &vmware.VROpsHostsystemResolver{},
19+
"vrops_project_noisiness_extractor": &vmware.VROpsProjectNoisinessExtractor{},
20+
"vrops_hostsystem_contention_long_term_extractor": &vmware.VROpsHostsystemContentionLongTermExtractor{},
21+
"vrops_hostsystem_contention_short_term_extractor": &vmware.VROpsHostsystemContentionShortTermExtractor{},
22+
// KVM-specific extractors
23+
"kvm_libvirt_domain_cpu_steal_pct_extractor": &kvm.LibvirtDomainCPUStealPctExtractor{},
24+
// NetApp-specific extractors
25+
"netapp_storage_pool_cpu_usage_extractor": &netapp.StoragePoolCPUUsageExtractor{},
26+
// Shared extractors
27+
"host_utilization_extractor": &shared.HostUtilizationExtractor{},
28+
"host_capabilities_extractor": &shared.HostCapabilitiesExtractor{},
29+
"vm_host_residency_extractor": &shared.VMHostResidencyExtractor{},
30+
"vm_life_span_histogram_extractor": &shared.VMLifeSpanHistogramExtractor{},
31+
"host_az_extractor": &shared.HostAZExtractor{},
32+
"host_pinned_projects_extractor": &shared.HostPinnedProjectsExtractor{},
33+
// SAP-specific extractors
34+
"sap_host_details_extractor": &sap.HostDetailsExtractor{},
35+
}

internal/knowledge/kpis/controller.go

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,6 @@ import (
1010

1111
"github.com/cobaltcore-dev/cortex/api/v1alpha1"
1212
"github.com/cobaltcore-dev/cortex/internal/knowledge/kpis/plugins"
13-
"github.com/cobaltcore-dev/cortex/internal/knowledge/kpis/plugins/kvm"
14-
"github.com/cobaltcore-dev/cortex/internal/knowledge/kpis/plugins/netapp"
15-
"github.com/cobaltcore-dev/cortex/internal/knowledge/kpis/plugins/sap"
16-
"github.com/cobaltcore-dev/cortex/internal/knowledge/kpis/plugins/shared"
17-
"github.com/cobaltcore-dev/cortex/internal/knowledge/kpis/plugins/vmware"
1813
"github.com/cobaltcore-dev/cortex/pkg/conf"
1914
"github.com/cobaltcore-dev/cortex/pkg/db"
2015
"github.com/cobaltcore-dev/cortex/pkg/multicluster"
@@ -33,36 +28,16 @@ import (
3328
"sigs.k8s.io/controller-runtime/pkg/reconcile"
3429
)
3530

36-
// Configuration of supported kpis.
37-
var SupportedKPIsByImpl = map[string]plugins.KPI{
38-
// KVM kpis.
39-
"kvm_host_capacity_kpi": &kvm.HostCapacityKPI{},
40-
// VMware kpis.
41-
"vmware_host_contention_kpi": &vmware.VMwareHostContentionKPI{},
42-
"vmware_project_noisiness_kpi": &vmware.VMwareProjectNoisinessKPI{},
43-
// NetApp kpis.
44-
"netapp_storage_pool_cpu_usage_kpi": &netapp.NetAppStoragePoolCPUUsageKPI{},
45-
// Shared kpis.
46-
"vm_migration_statistics_kpi": &shared.VMMigrationStatisticsKPI{},
47-
"vm_life_span_kpi": &shared.VMLifeSpanKPI{},
48-
"vm_commitments_kpi": &shared.VMCommitmentsKPI{},
49-
// SAP kpis.
50-
"sap_host_total_allocatable_capacity_kpi": &sap.HostTotalAllocatableCapacityKPI{},
51-
"sap_host_capacity_kpi": &sap.HostAvailableCapacityKPI{},
52-
"sap_host_running_vms_kpi": &sap.HostRunningVMsKPI{},
53-
"sap_flavor_running_vms_kpi": &sap.FlavorRunningVMsKPI{},
54-
}
55-
5631
// The kpi controller checks the status of kpi dependencies and populates
5732
// the kpi status accordingly.
5833
type Controller struct {
5934
// Kubernetes client to manage/fetch resources.
6035
client.Client
61-
// The supported kpis to manage.
62-
SupportedKPIsByImpl map[string]plugins.KPI
6336
// The name of the operator to scope resources to.
6437
OperatorName string
6538

39+
// The supported kpis to manage.
40+
supportedKPIs map[string]plugins.KPI
6641
// Registered kpis by name.
6742
registeredKPIsByResourceName map[string]plugins.KPI
6843
}
@@ -92,7 +67,7 @@ func (c *Controller) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
9267
}
9368

9469
// If this kpi is not supported, ignore it.
95-
if _, ok := c.SupportedKPIsByImpl[kpi.Spec.Impl]; !ok {
70+
if _, ok := c.supportedKPIs[kpi.Spec.Impl]; !ok {
9671
log.Info("kpi: unsupported kpi, ignoring", "name", req.Name)
9772
return ctrl.Result{}, nil
9873
}
@@ -248,7 +223,7 @@ func (c *Controller) handleKPIChange(ctx context.Context, obj *v1alpha1.KPI) err
248223
if dependenciesReadyTotal == dependenciesTotal && !registered {
249224
log.Info("kpi: registering new kpi", "name", obj.Name)
250225
var ok bool
251-
registeredKPI, ok = c.SupportedKPIsByImpl[obj.Spec.Impl]
226+
registeredKPI, ok = c.supportedKPIs[obj.Spec.Impl]
252227
if !ok {
253228
return fmt.Errorf("kpi %s not supported", obj.Name)
254229
}
@@ -422,6 +397,9 @@ func (c *Controller) handleKnowledgeDeleted(
422397
}
423398

424399
func (c *Controller) SetupWithManager(mgr manager.Manager, mcl *multicluster.Client) error {
400+
if c.supportedKPIs == nil { // This can be overridden for tests.
401+
c.supportedKPIs = supportedKPIs
402+
}
425403
if err := mgr.Add(manager.RunnableFunc(c.InitAllKPIs)); err != nil {
426404
return err
427405
}

0 commit comments

Comments
 (0)