kubernetes-operator/pkg/controller/jenkins/notifications/sender.go

132 lines
3.8 KiB
Go

package notifications
import (
"fmt"
"net/http"
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
"github.com/jenkinsci/kubernetes-operator/pkg/event"
"github.com/jenkinsci/kubernetes-operator/pkg/log"
"github.com/pkg/errors"
k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
)
const (
infoTitleText = "Jenkins Operator reconciliation info"
warnTitleText = "Jenkins Operator reconciliation warning"
messageFieldName = "Message"
loggingLevelFieldName = "Logging Level"
crNameFieldName = "CR Name"
phaseFieldName = "Phase"
namespaceFieldName = "Namespace"
footerContent = "Powered by Jenkins Operator"
)
const (
// PhaseBase is core configuration of Jenkins provided by the Operator
PhaseBase Phase = "base"
// PhaseUser is user-defined configuration of Jenkins
PhaseUser Phase = "user"
// PhaseUnknown is untraceable type of configuration
PhaseUnknown Phase = "unknown"
)
var (
testPhase = PhaseUser
testCrName = "test-cr"
testNamespace = "default"
testMessage = "test-message"
testMessageVerbose = []string{"detail-test-message"}
testLoggingLevel = v1alpha2.NotificationLogLevelWarning
client = http.Client{}
)
// Phase defines the type of configuration
type Phase string
// StatusColor is useful for better UX
type StatusColor string
// LoggingLevel is type for selecting different logging levels
type LoggingLevel string
// Event contains event details which will be sent as a notification
type Event struct {
Jenkins v1alpha2.Jenkins
Phase Phase
LogLevel v1alpha2.NotificationLogLevel
Message string
MessagesVerbose []string
}
type service interface {
Send(event Event, notificationConfig v1alpha2.Notification) error
}
// Listen listens for incoming events and send it as notifications
func Listen(events chan Event, k8sEvent event.Recorder, k8sClient k8sclient.Client) {
for evt := range events {
logger := log.Log.WithValues("cr", evt.Jenkins.Name)
for _, notificationConfig := range evt.Jenkins.Spec.Notifications {
var err error
var svc service
if notificationConfig.Slack != nil {
svc = Slack{k8sClient: k8sClient}
} else if notificationConfig.Teams != nil {
svc = Teams{k8sClient: k8sClient}
} else if notificationConfig.Mailgun != nil {
svc = MailGun{k8sClient: k8sClient}
} else {
logger.V(log.VWarn).Info(fmt.Sprintf("Unknown notification service `%+v`", notificationConfig))
continue
}
go func(notificationConfig v1alpha2.Notification) {
err = notify(svc, evt, notificationConfig)
if err != nil {
if log.Debug {
logger.Error(nil, fmt.Sprintf("%+v", errors.WithMessage(err, fmt.Sprintf("failed to send notification '%s'", notificationConfig.Name))))
} else {
logger.Error(nil, fmt.Sprintf("%s", errors.WithMessage(err, fmt.Sprintf("failed to send notification '%s'", notificationConfig.Name))))
}
}
}(notificationConfig)
}
k8sEvent.Emit(&evt.Jenkins, logLevelEventType(evt.LogLevel), "NotificationSent", evt.Message)
}
}
func logLevelEventType(level v1alpha2.NotificationLogLevel) event.Type {
switch level {
case v1alpha2.NotificationLogLevelWarning:
return event.TypeWarning
case v1alpha2.NotificationLogLevelInfo:
return event.TypeNormal
default:
return event.TypeNormal
}
}
func notify(svc service, event Event, manifest v1alpha2.Notification) error {
if event.LogLevel == v1alpha2.NotificationLogLevelInfo && manifest.LoggingLevel == v1alpha2.NotificationLogLevelWarning {
return nil
}
return svc.Send(event, manifest)
}
func notificationTitle(event Event) string {
if event.LogLevel == v1alpha2.NotificationLogLevelInfo {
return infoTitleText
} else if event.LogLevel == v1alpha2.NotificationLogLevelWarning {
return warnTitleText
} else {
return ""
}
}