Skip to content

Commit

Permalink
Mimir enabled: Delete per cluster heartbeat alertmanagerconfigs
Browse files Browse the repository at this point in the history
Signed-off-by: QuentinBisson <[email protected]>
  • Loading branch information
QuentinBisson committed Jun 3, 2024
1 parent 2a9a170 commit 7676c42
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 67 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed

- Delete per cluster heartbeats when Mimir is enabled.
- Delete per cluster heartbeat alertmanager wiring when Mimir is enabled.

## [4.75.1] - 2024-05-23

Expand Down
2 changes: 2 additions & 0 deletions service/controller/clusterapi/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ func New(config Config) ([]resource.Interface, error) {

Installation: config.Installation,
Proxy: config.Proxy,

MimirEnabled: config.MimirEnabled,
}

heartbeatWebhookConfigResource, err = heartbeatwebhookconfig.New(c)
Expand Down
2 changes: 2 additions & 0 deletions service/controller/managementcluster/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ func newResources(config resourcesConfig) ([]resource.Interface, error) {

Installation: config.Installation,
Proxy: config.Proxy,

MimirEnabled: config.MimirEnabled,
}

heartbeatWebhookConfigResource, err = heartbeatwebhookconfig.New(c)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package heartbeatwebhookconfig

import (
"context"

"github.com/giantswarm/microerror"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func (r *Resource) EnsureCreated(ctx context.Context, obj interface{}) error {
if r.mimirEnabled {
return r.EnsureDeleted(ctx, obj)
}

desired, err := r.toAlertmanagerConfig(obj)
if err != nil {
return microerror.Mask(err)
}

r.logger.Debugf(ctx, "creating")
current, err := r.client.MonitoringV1alpha1().AlertmanagerConfigs(desired.GetNamespace()).Get(ctx, desired.GetName(), metav1.GetOptions{})
if apierrors.IsNotFound(err) {
current, err = r.client.MonitoringV1alpha1().AlertmanagerConfigs(desired.GetNamespace()).Create(ctx, desired, metav1.CreateOptions{})
}

if err != nil {
return microerror.Mask(err)
}

if r.hasChanged(current, desired) {
updateMeta(current, desired)
_, err = r.client.MonitoringV1alpha1().AlertmanagerConfigs(desired.GetNamespace()).Update(ctx, desired, metav1.UpdateOptions{})
if err != nil {
return microerror.Mask(err)
}
}
r.logger.Debugf(ctx, "created")

return nil
}

func updateMeta(c, d metav1.Object) {
d.SetGenerateName(c.GetGenerateName())
d.SetUID(c.GetUID())
d.SetResourceVersion(c.GetResourceVersion())
d.SetGeneration(c.GetGeneration())
d.SetSelfLink(c.GetSelfLink())
d.SetCreationTimestamp(c.GetCreationTimestamp())
d.SetDeletionTimestamp(c.GetDeletionTimestamp())
d.SetDeletionGracePeriodSeconds(c.GetDeletionGracePeriodSeconds())
// without this, it's impossible to change labels on resources
if len(d.GetLabels()) == 0 {
d.SetLabels(c.GetLabels())
}
// without this, it's impossible to change annotations on resources
if len(d.GetAnnotations()) == 0 {
d.SetAnnotations(c.GetAnnotations())
}
d.SetFinalizers(c.GetFinalizers())
d.SetOwnerReferences(c.GetOwnerReferences())
d.SetManagedFields(c.GetManagedFields())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package heartbeatwebhookconfig

import (
"context"

"github.com/giantswarm/microerror"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func (r *Resource) EnsureDeleted(ctx context.Context, obj interface{}) error {
object, err := r.getObjectMeta(obj)
if err != nil {
return microerror.Mask(err)
}

r.logger.Debugf(ctx, "deleting")
err = r.client.MonitoringV1alpha1().AlertmanagerConfigs(object.GetNamespace()).Delete(ctx, object.GetName(), metav1.DeleteOptions{})
if apierrors.IsNotFound(err) {
// fall through
} else if err != nil {
return microerror.Mask(err)
}
r.logger.Debugf(ctx, "deleted")

return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,3 @@ var invalidConfigError = &microerror.Error{
func IsInvalidConfig(err error) bool {
return microerror.Cause(err) == invalidConfigError
}

var wrongTypeError = &microerror.Error{
Kind: "wrongTypeError",
}

// IsWrongType asserts wrongTypeError.
func IsWrongType(err error) bool {
return microerror.Cause(err) == wrongTypeError
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@ import (
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
monitoringv1alpha1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1alpha1"
monitoringclient "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned"
"golang.org/x/net/context"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/giantswarm/prometheus-meta-operator/v2/service/controller/resource/generic"
"github.com/giantswarm/prometheus-meta-operator/v2/service/key"
)

Expand All @@ -26,35 +24,39 @@ type Config struct {
Logger micrologger.Logger
Installation string
Proxy func(reqURL *url.URL) (*url.URL, error)

MimirEnabled bool
}

func New(config Config) (*generic.Resource, error) {
clientFunc := func(namespace string) generic.Interface {
c := config.Client.MonitoringV1alpha1().AlertmanagerConfigs(namespace)
return wrappedClient{client: c}
}
type Resource struct {
client monitoringclient.Interface
logger micrologger.Logger
installation string
proxy func(reqURL *url.URL) (*url.URL, error)

c := generic.Config{
ClientFunc: clientFunc,
Logger: config.Logger,
Name: Name,
GetObjectMeta: func(ctx context.Context, v interface{}) (metav1.ObjectMeta, error) {
return getObjectMeta(v)
},
GetDesiredObject: func(ctx context.Context, v interface{}) (metav1.Object, error) {
return toAlertmanagerConfig(v, config)
},
HasChangedFunc: hasChanged,
mimirEnabled bool
}

func New(config Config) (*Resource, error) {
if config.Logger == nil {
return nil, microerror.Maskf(invalidConfigError, "%T.Logger must not be empty", config)
}
r, err := generic.New(c)
if err != nil {
return nil, microerror.Mask(err)
if config.Installation == "" {
return nil, microerror.Maskf(invalidConfigError, "%T.Installation must not be empty", config)
}

r := &Resource{
client: config.Client,
logger: config.Logger,
installation: config.Installation,
proxy: config.Proxy,
mimirEnabled: config.MimirEnabled,
}

return r, nil
}

func getObjectMeta(v interface{}) (metav1.ObjectMeta, error) {
func (r Resource) getObjectMeta(v interface{}) (metav1.ObjectMeta, error) {
cluster, err := key.ToCluster(v)
if err != nil {
return metav1.ObjectMeta{}, microerror.Mask(err)
Expand All @@ -67,12 +69,12 @@ func getObjectMeta(v interface{}) (metav1.ObjectMeta, error) {
}, nil
}

func toAlertmanagerConfig(v interface{}, config Config) (metav1.Object, error) {
func (r Resource) toAlertmanagerConfig(v interface{}) (*monitoringv1alpha1.AlertmanagerConfig, error) {
if v == nil {
return nil, nil
}

objectMeta, err := getObjectMeta(v)
objectMeta, err := r.getObjectMeta(v)
if err != nil {
return nil, microerror.Mask(err)
}
Expand All @@ -88,7 +90,7 @@ func toAlertmanagerConfig(v interface{}, config Config) (metav1.Object, error) {
}

sendResolved := false
urlAddress, err := url.Parse(key.HeartbeatAPI(cluster, config.Installation))
urlAddress, err := url.Parse(key.HeartbeatAPI(cluster, r.installation))
if err != nil {
return nil, microerror.Mask(err)
}
Expand All @@ -110,7 +112,7 @@ func toAlertmanagerConfig(v interface{}, config Config) (metav1.Object, error) {
if err != nil {
return nil, err
}
proxyURL, err := config.Proxy(opsgenieUrl)
proxyURL, err := r.proxy(opsgenieUrl)
if err != nil {
return nil, err
}
Expand All @@ -119,7 +121,7 @@ func toAlertmanagerConfig(v interface{}, config Config) (metav1.Object, error) {
}

receiver := monitoringv1alpha1.Receiver{
Name: key.HeartbeatReceiverName(cluster, config.Installation),
Name: key.HeartbeatReceiverName(cluster, r.installation),
WebhookConfigs: []monitoringv1alpha1.WebhookConfig{
{
URL: &address,
Expand All @@ -133,10 +135,10 @@ func toAlertmanagerConfig(v interface{}, config Config) (metav1.Object, error) {
ObjectMeta: objectMeta,
Spec: monitoringv1alpha1.AlertmanagerConfigSpec{
Route: &monitoringv1alpha1.Route{
Receiver: key.HeartbeatReceiverName(cluster, config.Installation),
Receiver: key.HeartbeatReceiverName(cluster, r.installation),
Matchers: []monitoringv1alpha1.Matcher{
{Name: key.ClusterIDKey, Value: key.ClusterID(cluster)},
{Name: key.InstallationKey, Value: config.Installation},
{Name: key.InstallationKey, Value: r.installation},
{Name: key.TypeKey, Value: key.Heartbeat()},
},
Continue: false,
Expand All @@ -154,9 +156,13 @@ func toAlertmanagerConfig(v interface{}, config Config) (metav1.Object, error) {
return alertmanagerConfig, nil
}

func hasChanged(current, desired metav1.Object) bool {
func (r Resource) hasChanged(current, desired metav1.Object) bool {
c := current.(*monitoringv1alpha1.AlertmanagerConfig)
d := desired.(*monitoringv1alpha1.AlertmanagerConfig)

return !reflect.DeepEqual(c.Spec, d.Spec)
}

func (r *Resource) Name() string {
return Name
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,38 @@ import (
"path/filepath"
"testing"

"github.com/giantswarm/micrologger"
"golang.org/x/net/http/httpproxy"

"github.com/giantswarm/prometheus-meta-operator/v2/pkg/unittest"
)

var update = flag.Bool("update", false, "update the output file")

func TestAlertmanager(t *testing.T) {
func TestAlertmanagerConfig(t *testing.T) {
var err error
var logger micrologger.Logger
{
c := micrologger.Config{}

logger, err = micrologger.New(c)
if err != nil {
t.Fatal(err)
}
}

proxyConfig := httpproxy.Config{}
config := Config{
Proxy: proxyConfig.ProxyFunc(),
Logger: logger,
Installation: "test-installation",
}

resource, err := New(config)
if err != nil {
t.Fatal(err)
}

for _, flavor := range unittest.ProviderFlavors {
outputDir, err := filepath.Abs("./test/" + flavor)
if err != nil {
Expand All @@ -29,7 +47,7 @@ func TestAlertmanager(t *testing.T) {
Flavor: flavor,
T: t,
TestFunc: func(v interface{}) (interface{}, error) {
return toAlertmanagerConfig(v, config)
return resource.toAlertmanagerConfig(v)
},
Update: *update,
}
Expand Down

0 comments on commit 7676c42

Please sign in to comment.