mirror of
https://github.com/hanzoai/deploy.git
synced 2026-10-07 08:44:50 +00:00
237 lines
6.8 KiB
Go
237 lines
6.8 KiB
Go
package settings
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/argoproj/notifications-engine/pkg/api"
|
|
"github.com/argoproj/notifications-engine/pkg/services"
|
|
"github.com/argoproj/notifications-engine/pkg/subscriptions"
|
|
"github.com/argoproj/notifications-engine/pkg/triggers"
|
|
"github.com/argoproj/notifications-engine/pkg/util/text"
|
|
jsonpatch "github.com/evanphx/json-patch"
|
|
log "github.com/sirupsen/logrus"
|
|
corev1 "k8s.io/api/core/v1"
|
|
"sigs.k8s.io/yaml"
|
|
)
|
|
|
|
type legacyTemplate struct {
|
|
Name string `json:"name,omitempty"`
|
|
Title string `json:"subject,omitempty"`
|
|
Body string `json:"body,omitempty"`
|
|
services.Notification
|
|
}
|
|
|
|
type legacyTrigger struct {
|
|
Name string `json:"name,omitempty"`
|
|
Condition string `json:"condition,omitempty"`
|
|
Description string `json:"description,omitempty"`
|
|
Template string `json:"template,omitempty"`
|
|
Enabled *bool `json:"enabled,omitempty"`
|
|
}
|
|
|
|
type legacyConfig struct {
|
|
Triggers []legacyTrigger `json:"triggers,omitempty"`
|
|
Templates []legacyTemplate `json:"templates,omitempty"`
|
|
Context map[string]string `json:"context,omitempty"`
|
|
Subscriptions subscriptions.DefaultSubscriptions `json:"subscriptions,omitempty"`
|
|
}
|
|
|
|
type legacyWebhookOptions struct {
|
|
services.WebhookOptions
|
|
Name string `json:"name"`
|
|
}
|
|
|
|
type legacyServicesConfig struct {
|
|
Email *services.EmailOptions `json:"email"`
|
|
Slack *services.SlackOptions `json:"slack"`
|
|
Opsgenie *services.OpsgenieOptions `json:"opsgenie"`
|
|
Grafana *services.GrafanaOptions `json:"grafana"`
|
|
Webhook []legacyWebhookOptions `json:"webhook"`
|
|
}
|
|
|
|
func mergePatch(orig any, other any) error {
|
|
origData, err := json.Marshal(orig)
|
|
if err != nil {
|
|
return fmt.Errorf("error marshaling json for original: %w", err)
|
|
}
|
|
otherData, err := json.Marshal(other)
|
|
if err != nil {
|
|
return fmt.Errorf("error marshaling json for patch: %w", err)
|
|
}
|
|
|
|
if string(otherData) == "null" {
|
|
return nil
|
|
}
|
|
|
|
mergedData, err := jsonpatch.MergePatch(origData, otherData)
|
|
if err != nil {
|
|
return fmt.Errorf("error creating merge patch: %w", err)
|
|
}
|
|
return json.Unmarshal(mergedData, orig)
|
|
}
|
|
|
|
func (legacy legacyConfig) merge(cfg *api.Config, context map[string]string) error {
|
|
if err := mergePatch(&context, &legacy.Context); err != nil {
|
|
return fmt.Errorf("error in merge: %w", err)
|
|
}
|
|
if err := mergePatch(&cfg.Subscriptions, &legacy.Subscriptions); err != nil {
|
|
return fmt.Errorf("error in merge config and legacy subscriptions: %w", err)
|
|
}
|
|
|
|
for _, template := range legacy.Templates {
|
|
t, ok := cfg.Templates[template.Name]
|
|
if ok {
|
|
if err := mergePatch(&t, &template.Notification); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if template.Title != "" {
|
|
if template.Email == nil {
|
|
template.Email = &services.EmailNotification{}
|
|
}
|
|
template.Email.Subject = template.Title
|
|
}
|
|
if template.Body != "" {
|
|
template.Message = template.Body
|
|
}
|
|
cfg.Templates[template.Name] = template.Notification
|
|
}
|
|
|
|
for _, trigger := range legacy.Triggers {
|
|
if trigger.Enabled != nil && *trigger.Enabled {
|
|
cfg.DefaultTriggers = append(cfg.DefaultTriggers, trigger.Name)
|
|
}
|
|
var firstCondition triggers.Condition
|
|
t, ok := cfg.Triggers[trigger.Name]
|
|
if !ok || len(t) == 0 {
|
|
t = []triggers.Condition{firstCondition}
|
|
} else {
|
|
firstCondition = t[0]
|
|
}
|
|
|
|
if trigger.Condition != "" {
|
|
firstCondition.When = trigger.Condition
|
|
}
|
|
if trigger.Template != "" {
|
|
firstCondition.Send = []string{trigger.Template}
|
|
}
|
|
if trigger.Description != "" {
|
|
firstCondition.Description = trigger.Description
|
|
}
|
|
t[0] = firstCondition
|
|
cfg.Triggers[trigger.Name] = t
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *legacyServicesConfig) merge(cfg *api.Config) {
|
|
if c.Email != nil {
|
|
cfg.Services["email"] = func() (services.NotificationService, error) {
|
|
return services.NewEmailService(*c.Email), nil
|
|
}
|
|
}
|
|
if c.Slack != nil {
|
|
cfg.Services["slack"] = func() (services.NotificationService, error) {
|
|
return services.NewSlackService(*c.Slack), nil
|
|
}
|
|
}
|
|
if c.Grafana != nil {
|
|
cfg.Services["grafana"] = func() (services.NotificationService, error) {
|
|
return services.NewGrafanaService(*c.Grafana), nil
|
|
}
|
|
}
|
|
if c.Opsgenie != nil {
|
|
cfg.Services["opsgenie"] = func() (services.NotificationService, error) {
|
|
return services.NewOpsgenieService(*c.Opsgenie), nil
|
|
}
|
|
}
|
|
for i := range c.Webhook {
|
|
opts := c.Webhook[i]
|
|
cfg.Services[opts.Name] = func() (services.NotificationService, error) {
|
|
return services.NewWebhookService(opts.WebhookOptions), nil
|
|
}
|
|
}
|
|
}
|
|
|
|
// ApplyLegacyConfig settings specified using deprecated config map and secret keys
|
|
func ApplyLegacyConfig(cfg *api.Config, context map[string]string, cm *corev1.ConfigMap, secret *corev1.Secret) error {
|
|
if notifiersData, ok := secret.Data["notifiers.yaml"]; ok && len(notifiersData) > 0 {
|
|
log.Warn("Key 'notifiers.yaml' in Secret is deprecated, please migrate to new settings")
|
|
legacyServices := &legacyServicesConfig{}
|
|
err := yaml.Unmarshal(notifiersData, legacyServices)
|
|
if err != nil {
|
|
return fmt.Errorf("error unmarshaling legacy services config: %w", err)
|
|
}
|
|
legacyServices.merge(cfg)
|
|
}
|
|
|
|
if configData, ok := cm.Data["config.yaml"]; ok && configData != "" {
|
|
log.Warn("Key 'config.yaml' in ConfigMap is deprecated, please migrate to new settings")
|
|
legacyCfg := &legacyConfig{}
|
|
err := yaml.Unmarshal([]byte(configData), legacyCfg)
|
|
if err != nil {
|
|
return fmt.Errorf("error in unmarshaling legacy config: %w", err)
|
|
}
|
|
err = legacyCfg.merge(cfg, context)
|
|
if err != nil {
|
|
return fmt.Errorf("error in ApplyLegacyConfig merging config map: %w", err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
const (
|
|
annotationKey = "recipients.argocd-notifications.argoproj.io"
|
|
)
|
|
|
|
func GetLegacyDestinations(annotations map[string]string, defaultTriggers []string, serviceDefaultTriggers map[string][]string) services.Destinations {
|
|
dests := services.Destinations{}
|
|
for k, v := range annotations {
|
|
if !strings.HasSuffix(k, annotationKey) {
|
|
continue
|
|
}
|
|
|
|
var triggerNames []string
|
|
triggerName := strings.TrimRight(k[0:len(k)-len(annotationKey)], ".")
|
|
if triggerName == "" {
|
|
triggerNames = defaultTriggers
|
|
} else {
|
|
triggerNames = []string{triggerName}
|
|
}
|
|
|
|
for _, recipient := range text.SplitRemoveEmpty(v, ",") {
|
|
if recipient = strings.TrimSpace(recipient); recipient == "" {
|
|
continue
|
|
}
|
|
parts := strings.Split(recipient, ":")
|
|
dest := services.Destination{Service: parts[0]}
|
|
if len(parts) > 1 {
|
|
dest.Recipient = parts[1]
|
|
}
|
|
|
|
t := triggerNames
|
|
if v, ok := serviceDefaultTriggers[dest.Service]; ok {
|
|
t = v
|
|
}
|
|
for _, name := range t {
|
|
dests[name] = append(dests[name], dest)
|
|
}
|
|
}
|
|
}
|
|
return dests
|
|
}
|
|
|
|
// injectLegacyVar injects legacy variable into context
|
|
func injectLegacyVar(ctx map[string]string, serviceType string) map[string]string {
|
|
res := map[string]string{
|
|
"notificationType": serviceType,
|
|
}
|
|
for k, v := range ctx {
|
|
res[k] = v
|
|
}
|
|
return res
|
|
}
|