Skip to content

Commit 1cbfb7d

Browse files
sradcoAI Assistant
andcommitted
alert-mgmt-01: k8s foundation and server bootstrap for alert management API
Signed-off-by: Shirly Radco <sradco@redhat.com> Signed-off-by: João Vilaça <jvilaca@redhat.com> Signed-off-by: Aviv Litman <alitman@redhat.com> Co-authored-by: AI Assistant <noreply@cursor.com>
1 parent 7681f5e commit 1cbfb7d

File tree

5 files changed

+45
-153
lines changed

5 files changed

+45
-153
lines changed

cmd/plugin-backend.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,16 @@ import (
88
"strconv"
99
"strings"
1010

11-
server "github.com/openshift/monitoring-plugin/pkg"
1211
"github.com/sirupsen/logrus"
12+
13+
server "github.com/openshift/monitoring-plugin/pkg"
1314
)
1415

1516
var (
1617
portArg = flag.Int("port", 0, "server port to listen on (default: 9443)\nports 9444 and 9445 reserved for other use")
1718
certArg = flag.String("cert", "", "cert file path to enable TLS (disabled by default)")
1819
keyArg = flag.String("key", "", "private key file path to enable TLS (disabled by default)")
19-
featuresArg = flag.String("features", "", "enabled features, comma separated.\noptions: ['acm-alerting', 'incidents', 'dev-config', 'perses-dashboards']")
20+
featuresArg = flag.String("features", "", "enabled features, comma separated.\noptions: ['acm-alerting', 'incidents', 'dev-config', 'perses-dashboards', 'alert-management-api']")
2021
staticPathArg = flag.String("static-path", "", "static files path to serve frontend (default: './web/dist')")
2122
configPathArg = flag.String("config-path", "", "config files path (default: './config')")
2223
pluginConfigArg = flag.String("plugin-config-path", "", "plugin yaml configuration")

pkg/k8s/client.go

Lines changed: 2 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"k8s.io/client-go/rest"
99

1010
osmv1client "github.com/openshift/client-go/monitoring/clientset/versioned"
11-
routeclient "github.com/openshift/client-go/route/clientset/versioned"
1211
monitoringv1client "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned"
1312
"github.com/sirupsen/logrus"
1413
)
@@ -23,14 +22,8 @@ type client struct {
2322
osmv1clientset *osmv1client.Clientset
2423
config *rest.Config
2524

26-
prometheusAlerts *prometheusAlerts
27-
28-
prometheusRuleManager *prometheusRuleManager
29-
alertRelabelConfigManager *alertRelabelConfigManager
30-
alertingRuleManager *alertingRuleManager
31-
namespaceManager *namespaceManager
32-
relabeledRulesManager *relabeledRulesManager
33-
clusterMonitoringConfig *clusterMonitoringConfigManager
25+
prometheusRuleManager *prometheusRuleManager
26+
namespaceManager *namespaceManager
3427
}
3528

3629
func newClient(ctx context.Context, config *rest.Config) (Client, error) {
@@ -49,11 +42,6 @@ func newClient(ctx context.Context, config *rest.Config) (Client, error) {
4942
return nil, fmt.Errorf("failed to create osmv1 clientset: %w", err)
5043
}
5144

52-
routeClientset, err := routeclient.NewForConfig(config)
53-
if err != nil {
54-
return nil, fmt.Errorf("failed to create route clientset: %w", err)
55-
}
56-
5745
c := &client{
5846
clientset: clientset,
5947
monitoringv1clientset: monitoringv1clientset,
@@ -63,33 +51,11 @@ func newClient(ctx context.Context, config *rest.Config) (Client, error) {
6351

6452
c.prometheusRuleManager = newPrometheusRuleManager(ctx, monitoringv1clientset)
6553

66-
c.prometheusAlerts = newPrometheusAlerts(routeClientset, clientset.CoreV1(), config, c.prometheusRuleManager)
67-
68-
c.alertRelabelConfigManager, err = newAlertRelabelConfigManager(ctx, osmv1clientset)
69-
if err != nil {
70-
return nil, fmt.Errorf("failed to create alert relabel config manager: %w", err)
71-
}
72-
73-
c.alertingRuleManager, err = newAlertingRuleManager(ctx, osmv1clientset)
74-
if err != nil {
75-
return nil, fmt.Errorf("failed to create alerting rule manager: %w", err)
76-
}
77-
7854
c.namespaceManager, err = newNamespaceManager(ctx, clientset)
7955
if err != nil {
8056
return nil, fmt.Errorf("failed to create namespace manager: %w", err)
8157
}
8258

83-
c.clusterMonitoringConfig, err = newClusterMonitoringConfigManager(ctx, clientset)
84-
if err != nil {
85-
return nil, fmt.Errorf("failed to create cluster monitoring config manager: %w", err)
86-
}
87-
88-
c.relabeledRulesManager, err = newRelabeledRulesManager(ctx, c.namespaceManager, c.alertRelabelConfigManager, monitoringv1clientset, clientset)
89-
if err != nil {
90-
return nil, fmt.Errorf("failed to create relabeled rules config manager: %w", err)
91-
}
92-
9359
return c, nil
9460
}
9561

@@ -101,26 +67,10 @@ func (c *client) TestConnection(_ context.Context) error {
10167
return nil
10268
}
10369

104-
func (c *client) PrometheusAlerts() PrometheusAlertsInterface {
105-
return c.prometheusAlerts
106-
}
107-
10870
func (c *client) PrometheusRules() PrometheusRuleInterface {
10971
return c.prometheusRuleManager
11072
}
11173

112-
func (c *client) AlertRelabelConfigs() AlertRelabelConfigInterface {
113-
return c.alertRelabelConfigManager
114-
}
115-
116-
func (c *client) AlertingRules() AlertingRuleInterface {
117-
return c.alertingRuleManager
118-
}
119-
120-
func (c *client) RelabeledRules() RelabeledRulesInterface {
121-
return c.relabeledRulesManager
122-
}
123-
12474
func (c *client) Namespace() NamespaceInterface {
12575
return c.namespaceManager
12676
}

pkg/k8s/namespace.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,11 @@ func (nm *namespaceManager) updateMonitoringNamespace(ns *corev1.Namespace) {
9090
nm.mu.Lock()
9191
defer nm.mu.Unlock()
9292

93-
nm.monitoringNamespaces[ns.Name] = true
93+
if ns.Labels != nil && ns.Labels[ClusterMonitoringLabel] == "true" {
94+
nm.monitoringNamespaces[ns.Name] = true
95+
} else {
96+
delete(nm.monitoringNamespaces, ns.Name)
97+
}
9498
}
9599

96100
func (nm *namespaceManager) removeMonitoringNamespace(name string) {

pkg/k8s/types.go

Lines changed: 17 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ package k8s
33
import (
44
"context"
55

6-
osmv1 "github.com/openshift/api/monitoring/v1"
76
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
8-
"github.com/prometheus/prometheus/model/relabel"
97
"k8s.io/apimachinery/pkg/types"
108
)
119

@@ -21,23 +19,29 @@ type Client interface {
2119
// TestConnection tests the connection to the Kubernetes cluster
2220
TestConnection(ctx context.Context) error
2321

24-
// PrometheusAlerts retrieves active Prometheus alerts
25-
PrometheusAlerts() PrometheusAlertsInterface
26-
2722
// PrometheusRules returns the PrometheusRule interface
2823
PrometheusRules() PrometheusRuleInterface
2924

30-
// AlertRelabelConfigs returns the AlertRelabelConfig interface
31-
AlertRelabelConfigs() AlertRelabelConfigInterface
25+
// Namespace returns the Namespace interface
26+
Namespace() NamespaceInterface
27+
}
3228

33-
// AlertingRules returns the AlertingRule interface
34-
AlertingRules() AlertingRuleInterface
29+
// PrometheusRuleInterface defines operations for managing PrometheusRules
30+
type PrometheusRuleInterface interface {
31+
// List lists all PrometheusRules in the cluster
32+
List(ctx context.Context, namespace string) ([]monitoringv1.PrometheusRule, error)
3533

36-
// RelabeledRules returns the RelabeledRules interface
37-
RelabeledRules() RelabeledRulesInterface
34+
// Get retrieves a PrometheusRule by namespace and name
35+
Get(ctx context.Context, namespace string, name string) (*monitoringv1.PrometheusRule, bool, error)
3836

39-
// Namespace returns the Namespace interface
40-
Namespace() NamespaceInterface
37+
// Update updates an existing PrometheusRule
38+
Update(ctx context.Context, pr monitoringv1.PrometheusRule) error
39+
40+
// Delete deletes a PrometheusRule by namespace and name
41+
Delete(ctx context.Context, namespace string, name string) error
42+
43+
// AddRule adds a new rule to the specified PrometheusRule
44+
AddRule(ctx context.Context, namespacedName types.NamespacedName, groupName string, rule monitoringv1.Rule) error
4145
}
4246

4347
// RouteStatus describes the availability state of a monitoring route.
@@ -71,81 +75,6 @@ type AlertingHealth struct {
7175
UserWorkload *AlertingStackHealth `json:"userWorkload"`
7276
}
7377

74-
// PrometheusAlertsInterface defines operations for managing PrometheusAlerts
75-
type PrometheusAlertsInterface interface {
76-
// GetAlerts retrieves Prometheus alerts with optional state filtering
77-
GetAlerts(ctx context.Context, req GetAlertsRequest) ([]PrometheusAlert, error)
78-
// GetRules retrieves Prometheus alerting rules and active alerts
79-
GetRules(ctx context.Context, req GetRulesRequest) ([]PrometheusRuleGroup, error)
80-
}
81-
82-
// PrometheusRuleInterface defines operations for managing PrometheusRules
83-
type PrometheusRuleInterface interface {
84-
// List lists all PrometheusRules in the cluster
85-
List(ctx context.Context, namespace string) ([]monitoringv1.PrometheusRule, error)
86-
87-
// Get retrieves a PrometheusRule by namespace and name
88-
Get(ctx context.Context, namespace string, name string) (*monitoringv1.PrometheusRule, bool, error)
89-
90-
// Update updates an existing PrometheusRule
91-
Update(ctx context.Context, pr monitoringv1.PrometheusRule) error
92-
93-
// Delete deletes a PrometheusRule by namespace and name
94-
Delete(ctx context.Context, namespace string, name string) error
95-
96-
// AddRule adds a new rule to the specified PrometheusRule
97-
AddRule(ctx context.Context, namespacedName types.NamespacedName, groupName string, rule monitoringv1.Rule) error
98-
}
99-
100-
// AlertRelabelConfigInterface defines operations for managing AlertRelabelConfigs
101-
type AlertRelabelConfigInterface interface {
102-
// List lists all AlertRelabelConfigs in the cluster
103-
List(ctx context.Context, namespace string) ([]osmv1.AlertRelabelConfig, error)
104-
105-
// Get retrieves an AlertRelabelConfig by namespace and name
106-
Get(ctx context.Context, namespace string, name string) (*osmv1.AlertRelabelConfig, bool, error)
107-
108-
// Create creates a new AlertRelabelConfig
109-
Create(ctx context.Context, arc osmv1.AlertRelabelConfig) (*osmv1.AlertRelabelConfig, error)
110-
111-
// Update updates an existing AlertRelabelConfig
112-
Update(ctx context.Context, arc osmv1.AlertRelabelConfig) error
113-
114-
// Delete deletes an AlertRelabelConfig by namespace and name
115-
Delete(ctx context.Context, namespace string, name string) error
116-
}
117-
118-
// AlertingRuleInterface defines operations for managing AlertingRules
119-
// in the cluster monitoring namespace
120-
type AlertingRuleInterface interface {
121-
// List lists all AlertingRules in the cluster
122-
List(ctx context.Context) ([]osmv1.AlertingRule, error)
123-
124-
// Get retrieves an AlertingRule by name
125-
Get(ctx context.Context, name string) (*osmv1.AlertingRule, bool, error)
126-
127-
// Create creates a new AlertingRule
128-
Create(ctx context.Context, ar osmv1.AlertingRule) (*osmv1.AlertingRule, error)
129-
130-
// Update updates an existing AlertingRule
131-
Update(ctx context.Context, ar osmv1.AlertingRule) error
132-
133-
// Delete deletes an AlertingRule by name
134-
Delete(ctx context.Context, name string) error
135-
}
136-
137-
// RelabeledRulesInterface defines operations for managing relabeled rules
138-
type RelabeledRulesInterface interface {
139-
// List retrieves the relabeled rules for a given PrometheusRule
140-
List(ctx context.Context) []monitoringv1.Rule
141-
142-
// Get retrieves the relabeled rule for a given id
143-
Get(ctx context.Context, id string) (monitoringv1.Rule, bool)
144-
145-
// Config returns the list of alert relabel configs
146-
Config() []*relabel.Config
147-
}
148-
14978
// NamespaceInterface defines operations for Namespaces
15079
type NamespaceInterface interface {
15180
// IsClusterMonitoringNamespace checks if a namespace has the openshift.io/cluster-monitoring=true label

pkg/server.go

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212

1313
"github.com/gorilla/handlers"
1414
"github.com/gorilla/mux"
15-
"github.com/openshift/monitoring-plugin/pkg/proxy"
1615
"github.com/sirupsen/logrus"
1716
"gopkg.in/yaml.v2"
1817
v1 "k8s.io/api/core/v1"
@@ -21,6 +20,8 @@ import (
2120
"k8s.io/client-go/kubernetes/scheme"
2221
"k8s.io/client-go/rest"
2322
"k8s.io/client-go/tools/record"
23+
24+
"github.com/openshift/monitoring-plugin/pkg/proxy"
2425
)
2526

2627
var log = logrus.WithField("module", "server")
@@ -56,10 +57,11 @@ type PluginConfig struct {
5657
type Feature string
5758

5859
const (
59-
AcmAlerting Feature = "acm-alerting"
60-
Incidents Feature = "incidents"
61-
DevConfig Feature = "dev-config"
62-
PersesDashboards Feature = "perses-dashboards"
60+
AcmAlerting Feature = "acm-alerting"
61+
Incidents Feature = "incidents"
62+
DevConfig Feature = "dev-config"
63+
PersesDashboards Feature = "perses-dashboards"
64+
AlertManagementAPI Feature = "alert-management-api"
6365
)
6466

6567
func (pluginConfig *PluginConfig) MarshalJSON() ([]byte, error) {
@@ -103,6 +105,8 @@ func (s *PluginServer) Shutdown(ctx context.Context) error {
103105

104106
func createHTTPServer(ctx context.Context, cfg *Config) (*http.Server, error) {
105107
acmMode := cfg.Features[AcmAlerting]
108+
alertManagementAPIMode := cfg.Features[AlertManagementAPI]
109+
106110
acmLocationsLength := len(cfg.AlertmanagerUrl) + len(cfg.ThanosQuerierUrl)
107111

108112
if acmLocationsLength > 0 && !acmMode {
@@ -116,15 +120,19 @@ func createHTTPServer(ctx context.Context, cfg *Config) (*http.Server, error) {
116120
return nil, fmt.Errorf("cannot set default port to reserved port %d", cfg.Port)
117121
}
118122

123+
var k8sconfig *rest.Config
124+
var err error
125+
119126
// Uncomment the following line for local development:
120-
// k8sconfig, err := clientcmd.BuildConfigFromFlags("", "$HOME/.kube/config")
127+
// k8sconfig, err = clientcmd.BuildConfigFromFlags("", os.Getenv("KUBECONFIG"))
128+
// if err != nil {
129+
// return nil, fmt.Errorf("cannot get kubeconfig from file: %w", err)
130+
// }
121131

122132
// Comment the following line for local development:
123133
var k8sclient *dynamic.DynamicClient
124-
if acmMode {
125-
126-
k8sconfig, err := rest.InClusterConfig()
127-
134+
if acmMode || alertManagementAPIMode {
135+
k8sconfig, err = rest.InClusterConfig()
128136
if err != nil {
129137
return nil, fmt.Errorf("cannot get in cluster config: %w", err)
130138
}

0 commit comments

Comments
 (0)