Skip to content

Commit

Permalink
Remove alert package
Browse files Browse the repository at this point in the history
Alert was only used inside prometheus blocker, so it allows
to simplify the code.

Signed-off-by: Jean-Philippe Evrard <[email protected]>
  • Loading branch information
evrardjp committed Oct 19, 2024
1 parent bd23d59 commit 9fe2ca9
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 138 deletions.
28 changes: 10 additions & 18 deletions cmd/kured/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/kubereboot/kured/internal"
"github.com/kubereboot/kured/pkg/blockers"
"github.com/kubereboot/kured/pkg/checkers"
"github.com/prometheus/client_golang/prometheus/promhttp"
"math/rand"
"net/http"
"net/url"
Expand All @@ -19,8 +15,17 @@ import (
"time"

"github.com/containrrr/shoutrrr"
"github.com/kubereboot/kured/internal"
"github.com/kubereboot/kured/pkg/blockers"
"github.com/kubereboot/kured/pkg/checkers"
"github.com/kubereboot/kured/pkg/daemonsetlock"
"github.com/kubereboot/kured/pkg/delaytick"
"github.com/kubereboot/kured/pkg/reboot"
"github.com/kubereboot/kured/pkg/taints"
"github.com/kubereboot/kured/pkg/timewindow"
papi "github.com/prometheus/client_golang/api"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
log "github.com/sirupsen/logrus"
flag "github.com/spf13/pflag"
v1 "k8s.io/api/core/v1"
Expand All @@ -29,13 +34,6 @@ import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
kubectldrain "k8s.io/kubectl/pkg/drain"

"github.com/kubereboot/kured/pkg/alerts"
"github.com/kubereboot/kured/pkg/daemonsetlock"
"github.com/kubereboot/kured/pkg/delaytick"
"github.com/kubereboot/kured/pkg/reboot"
"github.com/kubereboot/kured/pkg/taints"
"github.com/kubereboot/kured/pkg/timewindow"
)

var (
Expand Down Expand Up @@ -609,12 +607,6 @@ func rebootAsRequired(nodeID string, rebooter reboot.Rebooter, checker checkers.
preferNoScheduleTaint.Disable()
}

// instantiate prometheus client
promClient, err := alerts.NewPromClient(papi.Config{Address: prometheusURL})
if err != nil {
log.Fatal("Unable to create prometheus client: ", err)
}

source = rand.NewSource(time.Now().UnixNano())
tick = delaytick.New(source, period)
for range tick {
Expand Down Expand Up @@ -655,7 +647,7 @@ func rebootAsRequired(nodeID string, rebooter reboot.Rebooter, checker checkers.

var blockCheckers []blockers.RebootBlocker
if prometheusURL != "" {
blockCheckers = append(blockCheckers, blockers.PrometheusBlockingChecker{PromClient: promClient, Filter: alertFilter.Regexp, FiringOnly: alertFiringOnly, FilterMatchOnly: alertFilterMatchOnly})
blockCheckers = append(blockCheckers, blockers.NewPrometheusBlockingChecker(papi.Config{Address: prometheusURL}, alertFilter.Regexp, alertFiringOnly, alertFilterMatchOnly))
}
if podSelectors != nil {
blockCheckers = append(blockCheckers, blockers.KubernetesBlockingChecker{Client: client, Nodename: nodeID, Filter: podSelectors})
Expand Down
77 changes: 0 additions & 77 deletions pkg/alerts/prometheus.go

This file was deleted.

37 changes: 0 additions & 37 deletions pkg/blockers/blockers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ package blockers
import (
"context"
"fmt"
"github.com/kubereboot/kured/pkg/alerts"
log "github.com/sirupsen/logrus"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"regexp"
)

// RebootBlocked checks that a single block Checker
Expand All @@ -27,20 +25,6 @@ type RebootBlocker interface {
IsBlocked() bool
}

// PrometheusBlockingChecker contains info for connecting
// to prometheus, and can give info about whether a reboot should be blocked
type PrometheusBlockingChecker struct {
// prometheusClient to make prometheus-go-client and api config available
// into the PrometheusBlockingChecker struct
PromClient *alerts.PromClient
// regexp used to get alerts
Filter *regexp.Regexp
// bool to indicate if only firing alerts should be considered
FiringOnly bool
// bool to indicate that we're only blocking on alerts which match the filter
FilterMatchOnly bool
}

// KubernetesBlockingChecker contains info for connecting
// to k8s, and can give info about whether a reboot should be blocked
type KubernetesBlockingChecker struct {
Expand All @@ -51,27 +35,6 @@ type KubernetesBlockingChecker struct {
Filter []string
}

// IsBlocked for the prometheus will check if there are active alerts matching
// the arguments given into promclient which would actively block the reboot.
// As of today, no blocker information is shared as a return of the method,
// and the information is simply logged.
func (pb PrometheusBlockingChecker) IsBlocked() bool {
alertNames, err := pb.PromClient.ActiveAlerts(pb.Filter, pb.FiringOnly, pb.FilterMatchOnly)
if err != nil {
log.Warnf("Reboot blocked: prometheus query error: %v", err)
return true
}
count := len(alertNames)
if count > 10 {
alertNames = append(alertNames[:10], "...")
}
if count > 0 {
log.Warnf("Reboot blocked: %d active alerts: %v", count, alertNames)
return true
}
return false
}

// IsBlocked for the KubernetesBlockingChecker will check if a pod, for the node, is preventing
// the reboot. It will warn in the logs about blocking, but does not return an error.
func (kb KubernetesBlockingChecker) IsBlocked() bool {
Expand Down
113 changes: 113 additions & 0 deletions pkg/blockers/prometheus.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package blockers

import (
"context"
"fmt"
papi "github.com/prometheus/client_golang/api"
v1 "github.com/prometheus/client_golang/api/prometheus/v1"
"github.com/prometheus/common/model"
log "github.com/sirupsen/logrus"
"regexp"
"sort"
"time"
)

// PrometheusBlockingChecker contains info for connecting
// to prometheus, and can give info about whether a reboot should be blocked
type PrometheusBlockingChecker struct {
PromConfig papi.Config
// regexp used to get alerts
Filter *regexp.Regexp
// bool to indicate if only firing alerts should be considered
FiringOnly bool
// bool to indicate that we're only blocking on alerts which match the filter
FilterMatchOnly bool
// storing the PromClient
PromClient papi.Client
}

func NewPrometheusBlockingChecker(config papi.Config, alertFilter *regexp.Regexp, firingOnly bool, filterMatchOnly bool) PrometheusBlockingChecker {
promClient, _ := papi.NewClient(config)

return PrometheusBlockingChecker{
PromConfig: config,
Filter: alertFilter,
FiringOnly: firingOnly,
FilterMatchOnly: filterMatchOnly,
PromClient: promClient,
}
}

// IsBlocked for the prometheus will check if there are active alerts matching
// the arguments given into the PrometheusBlockingChecker which would actively
// block the reboot.
// As of today, no blocker information is shared as a return of the method,
// and the information is simply logged.
func (pb PrometheusBlockingChecker) IsBlocked() bool {
alertNames, err := pb.ActiveAlerts()
if err != nil {
log.Warnf("Reboot blocked: prometheus query error: %v", err)
return true
}
count := len(alertNames)
if count > 10 {
alertNames = append(alertNames[:10], "...")
}
if count > 0 {
log.Warnf("Reboot blocked: %d active alerts: %v", count, alertNames)
return true
}
return false
}

// MetricLabel is used to give a fancier name
// than the type to the label for rebootBlockedCounter
func (pb PrometheusBlockingChecker) MetricLabel() string {
return "prometheus"
}

// ActiveAlerts is a method of type PromClient, it returns a list of names of active alerts
// (e.g. pending or firing), filtered by the supplied regexp or by the includeLabels query.
// filter by regexp means when the regexp finds the alert-name; the alert is excluded from the
// block-list and will NOT block rebooting. query by includeLabel means,
// if the query finds an alert, it will include it to the block-list, and it WILL block rebooting.
func (pb PrometheusBlockingChecker) ActiveAlerts() ([]string, error) {
api := v1.NewAPI(pb.PromClient)

// get all alerts from prometheus
value, _, err := api.Query(context.Background(), "ALERTS", time.Now())
if err != nil {
return nil, err
}

if value.Type() == model.ValVector {
if vector, ok := value.(model.Vector); ok {
activeAlertSet := make(map[string]bool)
for _, sample := range vector {
if alertName, isAlert := sample.Metric[model.AlertNameLabel]; isAlert && sample.Value != 0 {
if matchesRegex(pb.Filter, string(alertName), pb.FilterMatchOnly) && (!pb.FiringOnly || sample.Metric["alertstate"] == "firing") {
activeAlertSet[string(alertName)] = true
}
}
}

var activeAlerts []string
for activeAlert := range activeAlertSet {
activeAlerts = append(activeAlerts, activeAlert)
}
sort.Strings(activeAlerts)

return activeAlerts, nil
}
}

return nil, fmt.Errorf("unexpected value type %v", value)
}

func matchesRegex(filter *regexp.Regexp, alertName string, filterMatchOnly bool) bool {
if filter == nil {
return true
}

return filter.MatchString(alertName) == filterMatchOnly
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package alerts
package blockers

import (
"log"
Expand Down Expand Up @@ -145,12 +145,9 @@ func TestActiveAlerts(t *testing.T) {
regex, _ := regexp.Compile(tc.rFilter)

// instantiate the prometheus client with the mockserver-address
p, err := NewPromClient(api.Config{Address: mockServer.URL})
if err != nil {
log.Fatal(err)
}
p := NewPrometheusBlockingChecker(api.Config{Address: mockServer.URL}, regex, tc.firingOnly, tc.filterMatchOnly)

result, err := p.ActiveAlerts(regex, tc.firingOnly, tc.filterMatchOnly)
result, err := p.ActiveAlerts()
if err != nil {
log.Fatal(err)
}
Expand Down

0 comments on commit 9fe2ca9

Please sign in to comment.