180 lines
4.3 KiB
Go
180 lines
4.3 KiB
Go
package notifier
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"github.com/go-logr/logr"
|
|
|
|
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
|
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
|
corev1 "k8s.io/api/core/v1"
|
|
"k8s.io/apimachinery/pkg/types"
|
|
k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
|
|
)
|
|
|
|
var (
|
|
testConfigurationType = "test-configuration"
|
|
testCrName = "test-cr"
|
|
testStatus Status = 1
|
|
testError error
|
|
|
|
client = http.Client{}
|
|
)
|
|
|
|
const (
|
|
// StatusSuccess contains value for success state
|
|
StatusSuccess = 0
|
|
|
|
// StatusError contains value for error state
|
|
StatusError = 1
|
|
|
|
noErrorMessage = "No errors has found."
|
|
|
|
titleText = "Operator reconciled."
|
|
statusMessageFieldName = "Status message"
|
|
statusFieldName = "Status"
|
|
crNameFieldName = "CR Name"
|
|
configurationTypeFieldName = "Configuration Type"
|
|
footerContent = "Powered by Jenkins Operator <3"
|
|
)
|
|
|
|
// Status represents the state of operator
|
|
type Status int
|
|
|
|
// StatusColor is useful for better UX
|
|
type StatusColor string
|
|
|
|
// Information represents details about operator status
|
|
type Information struct {
|
|
ConfigurationType string
|
|
CrName string
|
|
Status Status
|
|
Error error
|
|
}
|
|
|
|
// Notification contains message which will be sent
|
|
type Notification struct {
|
|
Jenkins *v1alpha2.Jenkins
|
|
K8sClient k8sclient.Client
|
|
Logger logr.Logger
|
|
|
|
// Recipient is mobile number or email address
|
|
// It's not used in Slack or Microsoft Teams
|
|
Recipient string
|
|
|
|
Information *Information
|
|
}
|
|
|
|
// Service is skeleton for additional services
|
|
type Service interface {
|
|
Send(secret string, i *Information) error
|
|
}
|
|
|
|
// Listen is goroutine that listens for incoming messages and sends it
|
|
func Listen(notification chan *Notification) {
|
|
n := <-notification
|
|
if len(n.Jenkins.Spec.Notification) > 0 {
|
|
for _, endpoint := range n.Jenkins.Spec.Notification {
|
|
var err error
|
|
var service Service
|
|
var selector v1alpha2.SecretKeySelector
|
|
secret := &corev1.Secret{}
|
|
|
|
if endpoint.Slack != (v1alpha2.Slack{}) {
|
|
n.Logger.V(log.VDebug).Info("Slack detected")
|
|
service = Slack{}
|
|
selector = endpoint.Slack.URLSecretKeySelector
|
|
} else if endpoint.Teams != (v1alpha2.Teams{}) {
|
|
n.Logger.V(log.VDebug).Info("Microsoft Teams detected")
|
|
service = Teams{}
|
|
selector = endpoint.Teams.URLSecretKeySelector
|
|
} else if endpoint.Mailgun != (v1alpha2.Mailgun{}) {
|
|
n.Logger.V(log.VDebug).Info("Mailgun detected")
|
|
service = Mailgun{
|
|
Domain: endpoint.Mailgun.Domain,
|
|
Recipient: endpoint.Mailgun.Recipient,
|
|
From: endpoint.Mailgun.From,
|
|
}
|
|
selector = endpoint.Mailgun.APIKeySecretKeySelector
|
|
} else {
|
|
n.Logger.Info("Notification service not found or not defined")
|
|
}
|
|
|
|
err = n.K8sClient.Get(context.TODO(), types.NamespacedName{Name: selector.Name, Namespace: n.Jenkins.Namespace}, secret)
|
|
if err != nil {
|
|
n.Logger.Info(fmt.Sprintf("Failed to get secret with name `%s`. %+v", selector.Name, err))
|
|
}
|
|
|
|
n.Logger.V(log.VDebug).Info(fmt.Sprintf("Endpoint URL: %s", string(secret.Data[selector.Key])))
|
|
err = notify(service, string(secret.Data[selector.Key]), n.Information)
|
|
|
|
if err != nil {
|
|
n.Logger.Info(fmt.Sprintf("Failed to send notifications. %+v", err))
|
|
} else {
|
|
n.Logger.Info("Sent notification")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func getStatusName(status Status) string {
|
|
switch status {
|
|
case StatusSuccess:
|
|
return "Success"
|
|
case StatusError:
|
|
return "Error"
|
|
default:
|
|
return "Undefined"
|
|
}
|
|
}
|
|
|
|
func getStatusColor(status Status, service Service) StatusColor {
|
|
switch service.(type) {
|
|
case Slack:
|
|
switch status {
|
|
case StatusSuccess:
|
|
return "good"
|
|
case StatusError:
|
|
return "danger"
|
|
default:
|
|
return "#c8c8c8"
|
|
}
|
|
case Teams:
|
|
switch status {
|
|
case StatusSuccess:
|
|
return "54A254"
|
|
case StatusError:
|
|
return "E81123"
|
|
default:
|
|
return "C8C8C8"
|
|
}
|
|
case Mailgun:
|
|
switch status {
|
|
case StatusSuccess:
|
|
return "green"
|
|
case StatusError:
|
|
return "red"
|
|
default:
|
|
return "gray"
|
|
}
|
|
default:
|
|
return "#c8c8c8"
|
|
}
|
|
}
|
|
|
|
func notify(service Service, secret string, i *Information) error {
|
|
var err error
|
|
switch svc := service.(type) {
|
|
case Slack:
|
|
err = svc.Send(secret, i)
|
|
case Teams:
|
|
err = svc.Send(secret, i)
|
|
case Mailgun:
|
|
err = svc.Send(secret, i)
|
|
}
|
|
|
|
return err
|
|
}
|