Alerting: Migrate notifications API to app-platform SDK application (#104424)
* introduce alerting notification app * move code as is and remove from old registry * update api server registration * update make file and remove unnecessary args, copy some useful make commands from dashboards * update codeowners * move constants inside module and remove dependency from grafana * add support for selectors to the app builder
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
package v0alpha1
|
||||
|
||||
const InternalPrefix = "grafana.com/"
|
||||
const ProvenanceStatusAnnotationKey = InternalPrefix + "provenance"
|
||||
const ProvenanceStatusNone = "none"
|
||||
@@ -11,6 +11,8 @@ import (
|
||||
"github.com/grafana/grafana-app-sdk/app"
|
||||
)
|
||||
|
||||
var ()
|
||||
|
||||
var appManifestData = app.ManifestData{
|
||||
AppName: "alerting",
|
||||
Group: "notifications.alerting.grafana.app",
|
||||
|
||||
@@ -6,16 +6,16 @@ import (
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
|
||||
"github.com/grafana/grafana/apps/alerting/common"
|
||||
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1"
|
||||
)
|
||||
|
||||
func (o *Receiver) GetProvenanceStatus() string {
|
||||
if o == nil || o.Annotations == nil {
|
||||
return ""
|
||||
}
|
||||
s, ok := o.Annotations[common.ProvenanceStatusAnnotationKey]
|
||||
s, ok := o.Annotations[v0alpha1.ProvenanceStatusAnnotationKey]
|
||||
if !ok || s == "" {
|
||||
return common.ProvenanceStatusNone
|
||||
return v0alpha1.ProvenanceStatusNone
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -25,9 +25,9 @@ func (o *Receiver) SetProvenanceStatus(status string) {
|
||||
o.Annotations = make(map[string]string, 1)
|
||||
}
|
||||
if status == "" {
|
||||
status = common.ProvenanceStatusNone
|
||||
status = v0alpha1.ProvenanceStatusNone
|
||||
}
|
||||
o.Annotations[common.ProvenanceStatusAnnotationKey] = status
|
||||
o.Annotations[v0alpha1.ProvenanceStatusAnnotationKey] = status
|
||||
}
|
||||
|
||||
func (o *Receiver) SetAccessControl(action string) {
|
||||
@@ -40,7 +40,7 @@ func (o *Receiver) SetAccessControl(action string) {
|
||||
// AccessControlAnnotation returns the key for the access control annotation for the given action.
|
||||
// Ex. grafana.com/access/canDelete.
|
||||
func AccessControlAnnotation(action string) string {
|
||||
return fmt.Sprintf("%s%s/%s", common.InternalPrefix, "access", action)
|
||||
return fmt.Sprintf("%s%s/%s", v0alpha1.InternalPrefix, "access", action)
|
||||
}
|
||||
|
||||
func (o *Receiver) SetInUse(routesCnt int, rules []string) {
|
||||
@@ -54,7 +54,7 @@ func (o *Receiver) SetInUse(routesCnt int, rules []string) {
|
||||
// InUseAnnotation returns the key for the in-use annotation for the given resource.
|
||||
// Ex. grafana.com/inUse/routes, grafana.com/inUse/rules.
|
||||
func InUseAnnotation(resource string) string {
|
||||
return fmt.Sprintf("%s%s/%s", common.InternalPrefix, "inUse", resource)
|
||||
return fmt.Sprintf("%s%s/%s", v0alpha1.InternalPrefix, "inUse", resource)
|
||||
}
|
||||
|
||||
func SelectableFields(obj *Receiver) fields.Set {
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
// schema is unexported to prevent accidental overwrites
|
||||
var (
|
||||
schemaReceiver = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &Receiver{}, &ReceiverList{}, resource.WithKind("Receiver"),
|
||||
resource.WithPlural("receivers"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{{
|
||||
resource.WithPlural("receivers"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{resource.SelectableField{
|
||||
FieldSelector: "spec.title",
|
||||
FieldValueFunc: func(o resource.Object) (string, error) {
|
||||
cast, ok := o.(*Receiver)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package v0alpha1
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/apps/alerting/common"
|
||||
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1"
|
||||
)
|
||||
|
||||
const UserDefinedRoutingTreeName = "user-defined"
|
||||
@@ -10,9 +10,9 @@ func (o *RoutingTree) GetProvenanceStatus() string {
|
||||
if o == nil || o.Annotations == nil {
|
||||
return ""
|
||||
}
|
||||
s, ok := o.Annotations[common.ProvenanceStatusAnnotationKey]
|
||||
s, ok := o.Annotations[v0alpha1.ProvenanceStatusAnnotationKey]
|
||||
if !ok || s == "" {
|
||||
return common.ProvenanceStatusNone
|
||||
return v0alpha1.ProvenanceStatusNone
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -22,7 +22,7 @@ func (o *RoutingTree) SetProvenanceStatus(status string) {
|
||||
o.Annotations = make(map[string]string, 1)
|
||||
}
|
||||
if status == "" {
|
||||
status = common.ProvenanceStatusNone
|
||||
status = v0alpha1.ProvenanceStatusNone
|
||||
}
|
||||
o.Annotations[common.ProvenanceStatusAnnotationKey] = status
|
||||
o.Annotations[v0alpha1.ProvenanceStatusAnnotationKey] = status
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
|
||||
"github.com/grafana/grafana/apps/alerting/common"
|
||||
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1"
|
||||
)
|
||||
|
||||
const DefaultTemplateTitle = "Built-in Templates"
|
||||
@@ -13,9 +13,9 @@ func (o *TemplateGroup) GetProvenanceStatus() string {
|
||||
if o == nil || o.Annotations == nil {
|
||||
return ""
|
||||
}
|
||||
s, ok := o.Annotations[common.ProvenanceStatusAnnotationKey]
|
||||
s, ok := o.Annotations[v0alpha1.ProvenanceStatusAnnotationKey]
|
||||
if !ok || s == "" {
|
||||
return common.ProvenanceStatusNone
|
||||
return v0alpha1.ProvenanceStatusNone
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -25,9 +25,9 @@ func (o *TemplateGroup) SetProvenanceStatus(status string) {
|
||||
o.Annotations = make(map[string]string, 1)
|
||||
}
|
||||
if status == "" {
|
||||
status = common.ProvenanceStatusNone
|
||||
status = v0alpha1.ProvenanceStatusNone
|
||||
}
|
||||
o.Annotations[common.ProvenanceStatusAnnotationKey] = status
|
||||
o.Annotations[v0alpha1.ProvenanceStatusAnnotationKey] = status
|
||||
}
|
||||
|
||||
func SelectableFields(obj *TemplateGroup) fields.Set {
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import (
|
||||
// schema is unexported to prevent accidental overwrites
|
||||
var (
|
||||
schemaTemplateGroup = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &TemplateGroup{}, &TemplateGroupList{}, resource.WithKind("TemplateGroup"),
|
||||
resource.WithPlural("templategroups"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{{
|
||||
resource.WithPlural("templategroups"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{resource.SelectableField{
|
||||
FieldSelector: "spec.title",
|
||||
FieldValueFunc: func(o resource.Object) (string, error) {
|
||||
cast, ok := o.(*TemplateGroup)
|
||||
|
||||
@@ -4,16 +4,16 @@ import (
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
|
||||
"github.com/grafana/grafana/apps/alerting/common"
|
||||
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1"
|
||||
)
|
||||
|
||||
func (o *TimeInterval) GetProvenanceStatus() string {
|
||||
if o == nil || o.Annotations == nil {
|
||||
return ""
|
||||
}
|
||||
s, ok := o.Annotations[common.ProvenanceStatusAnnotationKey]
|
||||
s, ok := o.Annotations[v0alpha1.ProvenanceStatusAnnotationKey]
|
||||
if !ok || s == "" {
|
||||
return common.ProvenanceStatusNone
|
||||
return v0alpha1.ProvenanceStatusNone
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -23,9 +23,9 @@ func (o *TimeInterval) SetProvenanceStatus(status string) {
|
||||
o.Annotations = make(map[string]string, 1)
|
||||
}
|
||||
if status == "" {
|
||||
status = common.ProvenanceStatusNone
|
||||
status = v0alpha1.ProvenanceStatusNone
|
||||
}
|
||||
o.Annotations[common.ProvenanceStatusAnnotationKey] = status
|
||||
o.Annotations[v0alpha1.ProvenanceStatusAnnotationKey] = status
|
||||
}
|
||||
|
||||
func SelectableFields(obj *TimeInterval) fields.Set {
|
||||
|
||||
@@ -8,9 +8,10 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/timeinterval/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
var UTCLocation = "UTC"
|
||||
|
||||
// +k8s:openapi-gen=false
|
||||
type IntervalMutator func(spec *v0alpha1.Interval)
|
||||
|
||||
@@ -62,7 +63,7 @@ func (t IntervalGenerator) generateLocation() *string {
|
||||
if rand.Int()%3 == 0 {
|
||||
return nil
|
||||
}
|
||||
return util.Pointer("UTC")
|
||||
return &UTCLocation
|
||||
}
|
||||
|
||||
func (t IntervalGenerator) generateMonth() string {
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import (
|
||||
// schema is unexported to prevent accidental overwrites
|
||||
var (
|
||||
schemaTimeInterval = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &TimeInterval{}, &TimeIntervalList{}, resource.WithKind("TimeInterval"),
|
||||
resource.WithPlural("timeintervals"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{{
|
||||
resource.WithPlural("timeintervals"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{resource.SelectableField{
|
||||
FieldSelector: "spec.name",
|
||||
FieldValueFunc: func(o resource.Object) (string, error) {
|
||||
cast, ok := o.(*TimeInterval)
|
||||
|
||||
@@ -1,5 +1,40 @@
|
||||
package apis
|
||||
|
||||
import "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
import (
|
||||
"maps"
|
||||
|
||||
var GroupVersion = schema.GroupVersion{Group: "notifications.alerting.grafana.app", Version: "v0alpha1"}
|
||||
sdkResource "github.com/grafana/grafana-app-sdk/resource"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/kube-openapi/pkg/common"
|
||||
|
||||
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1"
|
||||
receiverv0alpha1 "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/receiver/v0alpha1"
|
||||
routingtreev0alpha1 "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/routingtree/v0alpha1"
|
||||
templategroupv0alpha1 "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/templategroup/v0alpha1"
|
||||
timeintervalv0alpha1 "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/timeinterval/v0alpha1"
|
||||
)
|
||||
|
||||
func GetOpenAPIDefinitions(c common.ReferenceCallback) map[string]common.OpenAPIDefinition {
|
||||
tmpl := templategroupv0alpha1.GetOpenAPIDefinitions(c)
|
||||
tin := timeintervalv0alpha1.GetOpenAPIDefinitions(c)
|
||||
recv := receiverv0alpha1.GetOpenAPIDefinitions(c)
|
||||
rest := routingtreev0alpha1.GetOpenAPIDefinitions(c)
|
||||
result := make(map[string]common.OpenAPIDefinition, len(tmpl)+len(tin)+len(recv)+len(rest))
|
||||
maps.Copy(result, tmpl)
|
||||
maps.Copy(result, tin)
|
||||
maps.Copy(result, recv)
|
||||
maps.Copy(result, rest)
|
||||
return result
|
||||
}
|
||||
|
||||
func GetKinds() map[schema.GroupVersion][]sdkResource.Kind {
|
||||
result := map[schema.GroupVersion][]sdkResource.Kind{
|
||||
v0alpha1.GroupVersion: {
|
||||
receiverv0alpha1.Kind(),
|
||||
routingtreev0alpha1.Kind(),
|
||||
templategroupv0alpha1.Kind(),
|
||||
timeintervalv0alpha1.Kind(),
|
||||
},
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana-app-sdk/app"
|
||||
"github.com/grafana/grafana-app-sdk/logging"
|
||||
"github.com/grafana/grafana-app-sdk/simple"
|
||||
|
||||
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis"
|
||||
)
|
||||
|
||||
func New(cfg app.Config) (app.App, error) {
|
||||
managedKinds := make([]simple.AppManagedKind, 0)
|
||||
for _, kinds := range apis.GetKinds() {
|
||||
for _, kind := range kinds {
|
||||
managedKinds = append(managedKinds, simple.AppManagedKind{Kind: kind})
|
||||
}
|
||||
}
|
||||
|
||||
c := simple.AppConfig{
|
||||
Name: "alerting.notification",
|
||||
KubeConfig: cfg.KubeConfig,
|
||||
InformerConfig: simple.AppInformerConfig{
|
||||
ErrorHandler: func(ctx context.Context, err error) {
|
||||
logging.DefaultLogger.With("error", err).Error("Informer processing error")
|
||||
},
|
||||
},
|
||||
ManagedKinds: managedKinds,
|
||||
}
|
||||
|
||||
a, err := simple.NewApp(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = a.ValidateManifest(cfg.ManifestData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return a, nil
|
||||
}
|
||||
Reference in New Issue
Block a user