Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Senders initialization #804

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 45 additions & 34 deletions integration_tests/notifier/notifier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/moira-alert/moira/notifier"
"github.com/moira-alert/moira/notifier/events"
"github.com/moira-alert/moira/notifier/notifications"
. "github.com/smartystreets/goconvey/convey"
)

var senderSettings = map[string]string{
Expand Down Expand Up @@ -78,41 +79,51 @@ var event = moira.NotificationEvent{
func TestNotifier(t *testing.T) {
mockCtrl = gomock.NewController(t)
defer mockCtrl.Finish()
database := redis.NewTestDatabase(logger)
metricsSourceProvider := metricSource.CreateMetricSourceProvider(local.Create(database), nil)
database.SaveContact(&contact) //nolint
database.SaveSubscription(&subscription) //nolint
database.SaveTrigger(trigger.ID, &trigger) //nolint
database.PushNotificationEvent(&event, true) //nolint
notifier2 := notifier.NewNotifier(database, logger, notifierConfig, notifierMetrics, metricsSourceProvider, map[string]moira.ImageStore{})
sender := mock_moira_alert.NewMockSender(mockCtrl)
sender.EXPECT().Init(senderSettings, logger, location, dateTimeFormat).Return(nil)
notifier2.RegisterSender(senderSettings, sender) //nolint
sender.EXPECT().SendEvents(gomock.Any(), contact, triggerData, gomock.Any(), false).Return(nil).Do(func(arg0, arg1, arg2, arg3, arg4 interface{}) {
fmt.Print("SendEvents called. End test")
close(shutdown)
})

fetchEventsWorker := events.FetchEventsWorker{
Database: database,
Logger: logger,
Metrics: notifierMetrics,
Scheduler: notifier.NewScheduler(database, logger, notifierMetrics),
}

fetchNotificationsWorker := notifications.FetchNotificationsWorker{
Database: database,
Logger: logger,
Notifier: notifier2,
}

fetchEventsWorker.Start()
fetchNotificationsWorker.Start()

waitTestEnd()

fetchEventsWorker.Stop() //nolint
fetchNotificationsWorker.Stop() //nolint
Convey("TestNotifier", t, func() {
database := redis.NewTestDatabase(logger)
metricsSourceProvider := metricSource.CreateMetricSourceProvider(local.Create(database), nil)
err := database.SaveContact(&contact)
So(err, ShouldBeNil)
err = database.SaveSubscription(&subscription)
So(err, ShouldBeNil)
err = database.SaveTrigger(trigger.ID, &trigger)
So(err, ShouldBeNil)
err = database.PushNotificationEvent(&event, true)
So(err, ShouldBeNil)

notifier2 := notifier.NewNotifier(database, logger, notifierConfig, notifierMetrics, metricsSourceProvider, map[string]moira.ImageStore{})
kissken marked this conversation as resolved.
Show resolved Hide resolved
sender := mock_moira_alert.NewMockSender(mockCtrl)
err = notifier2.RegisterSender(senderSettings, sender)
So(err, ShouldBeNil)
sender.EXPECT().SendEvents(gomock.Any(), contact, triggerData, gomock.Any(), false).Return(nil).Do(func(arg0, arg1, arg2, arg3, arg4 interface{}) {
fmt.Print("SendEvents called. End test")
close(shutdown)
})

fetchEventsWorker := events.FetchEventsWorker{
Database: database,
Logger: logger,
Metrics: notifierMetrics,
Scheduler: notifier.NewScheduler(database, logger, notifierMetrics),
}

fetchNotificationsWorker := notifications.FetchNotificationsWorker{
Database: database,
Logger: logger,
Notifier: notifier2,
}

fetchEventsWorker.Start()
fetchNotificationsWorker.Start()

waitTestEnd()

err = fetchEventsWorker.Stop()
So(err, ShouldBeNil)
err = fetchNotificationsWorker.Stop()
So(err, ShouldBeNil)
})
}

func waitTestEnd() {
Expand Down
1 change: 0 additions & 1 deletion interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,6 @@ type Logger interface {
type Sender interface {
// TODO refactor: https://github.com/moira-alert/moira/issues/794
SendEvents(events NotificationEvents, contact ContactData, trigger TriggerData, plot [][]byte, throttled bool) error
Init(senderSettings map[string]string, logger Logger, location *time.Location, dateTimeFormat string) error
}

// ImageStore is the interface for image storage providers
Expand Down
15 changes: 0 additions & 15 deletions mock/moira-alert/sender.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 3 additions & 4 deletions notifier/notifier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,10 @@ func configureNotifier(t *testing.T) {
"type": "test",
}

sender.EXPECT().Init(senderSettings, logger, location, "15:04 02.01.2006").Return(nil)

notif.RegisterSender(senderSettings, sender) //nolint

Convey("Should return one sender", t, func() {
err := notif.RegisterSender(senderSettings, sender)
So(err, ShouldBeNil)

So(notif.GetSenders(), ShouldResemble, map[string]bool{"test": true})
})
}
Expand Down
83 changes: 45 additions & 38 deletions notifier/registrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@ import (
"strings"

"github.com/moira-alert/moira"
"github.com/moira-alert/moira/senders/discord"
"github.com/moira-alert/moira/senders/mail"
"github.com/moira-alert/moira/senders/mattermost"
"github.com/moira-alert/moira/senders/msteams"
"github.com/moira-alert/moira/senders/opsgenie"
"github.com/moira-alert/moira/senders/pagerduty"
"github.com/moira-alert/moira/senders/pushover"
"github.com/moira-alert/moira/senders/script"
"github.com/moira-alert/moira/senders/selfstate"
"github.com/moira-alert/moira/senders/slack"
"github.com/moira-alert/moira/senders/telegram"
"github.com/moira-alert/moira/senders/twilio"
"github.com/moira-alert/moira/senders/victorops"
"github.com/moira-alert/moira/senders/webhook"
// "github.com/moira-alert/moira/senders/kontur"
"github.com/moira-alert/moira/notifier/senders/discord"
"github.com/moira-alert/moira/notifier/senders/mail"
"github.com/moira-alert/moira/notifier/senders/mattermost"
"github.com/moira-alert/moira/notifier/senders/msteams"
"github.com/moira-alert/moira/notifier/senders/opsgenie"
"github.com/moira-alert/moira/notifier/senders/pagerduty"
"github.com/moira-alert/moira/notifier/senders/pushover"
"github.com/moira-alert/moira/notifier/senders/script"
"github.com/moira-alert/moira/notifier/senders/selfstate"
"github.com/moira-alert/moira/notifier/senders/slack"
"github.com/moira-alert/moira/notifier/senders/telegram"
"github.com/moira-alert/moira/notifier/senders/twilio"
"github.com/moira-alert/moira/notifier/senders/victorops"
"github.com/moira-alert/moira/notifier/senders/webhook"
// "github.com/moira-alert/moira/notifier/senders/kontur"
kissken marked this conversation as resolved.
Show resolved Hide resolved
)

const (
Expand All @@ -40,52 +40,62 @@ const (
mattermostSender = "mattermost"
)

// RegisterSenders watch on senders config and register all configured senders
// RegisterSenders creates all senders and registers them.
func (notifier *StandardNotifier) RegisterSenders(connector moira.Database) error { //nolint
kissken marked this conversation as resolved.
Show resolved Hide resolved
var err error
var (
sender moira.Sender
err error
)

for _, senderSettings := range notifier.config.Senders {
senderSettings["front_uri"] = notifier.config.FrontURL

switch senderSettings["type"] {
case mailSender:
err = notifier.RegisterSender(senderSettings, &mail.Sender{})
sender, err = mail.NewSender(senderSettings, notifier.logger, notifier.config.Location, notifier.config.DateTimeFormat)
case pushoverSender:
err = notifier.RegisterSender(senderSettings, &pushover.Sender{})
sender, err = pushover.NewSender(senderSettings, notifier.logger, notifier.config.Location)
case scriptSender:
err = notifier.RegisterSender(senderSettings, &script.Sender{})
sender, err = script.NewSender(senderSettings, notifier.logger)
case discordSender:
err = notifier.RegisterSender(senderSettings, &discord.Sender{DataBase: connector})
sender, err = discord.NewSender(senderSettings, notifier.logger, notifier.config.Location, connector)
case slackSender:
err = notifier.RegisterSender(senderSettings, &slack.Sender{})
sender, err = slack.NewSender(senderSettings, notifier.logger, notifier.config.Location)
case telegramSender:
err = notifier.RegisterSender(senderSettings, &telegram.Sender{DataBase: connector})
sender, err = telegram.NewSender(senderSettings, notifier.logger, notifier.config.Location, connector)
case msTeamsSender:
err = notifier.RegisterSender(senderSettings, &msteams.Sender{})
sender, err = msteams.NewSender(senderSettings, notifier.logger, notifier.config.Location)
case pagerdutySender:
err = notifier.RegisterSender(senderSettings, &pagerduty.Sender{ImageStores: notifier.imageStores})
sender = pagerduty.NewSender(senderSettings, notifier.logger, notifier.config.Location, notifier.imageStores)
case twilioSmsSender, twilioVoiceSender:
err = notifier.RegisterSender(senderSettings, &twilio.Sender{})
sender, err = twilio.NewSender(senderSettings, notifier.logger, notifier.config.Location)
case webhookSender:
err = notifier.RegisterSender(senderSettings, &webhook.Sender{})
sender, err = webhook.NewSender(senderSettings, notifier.logger)
case opsgenieSender:
err = notifier.RegisterSender(senderSettings, &opsgenie.Sender{ImageStores: notifier.imageStores})
sender, err = opsgenie.NewSender(senderSettings, notifier.logger, notifier.config.Location, notifier.imageStores)
case victoropsSender:
err = notifier.RegisterSender(senderSettings, &victorops.Sender{ImageStores: notifier.imageStores})
sender, err = victorops.NewSender(senderSettings, notifier.logger, notifier.config.Location, notifier.imageStores)
case mattermostSender:
err = notifier.RegisterSender(senderSettings, &mattermost.Sender{})
sender, err = mattermost.NewSender(senderSettings, notifier.config.Location)
// case "email":
// err = notifier.RegisterSender(senderSettings, &kontur.MailSender{})
// sender = kontur.NewMailSender(senderSettings, notifier.logger, notifier.config.Location, notifier.config.DateTimeFormat)
// case "phone":
// err = notifier.RegisterSender(senderSettings, &kontur.SmsSender{})
// sender = kontur.NewSmsSender(senderSettings, notifier.logger, notifier.config.Location)
default:
return fmt.Errorf("unknown sender type [%s]", senderSettings["type"])
}
if err != nil {
return err
return fmt.Errorf("failed to initialize sender [%s], err [%s]", senderSettings["type"], err.Error())
}
err = notifier.RegisterSender(senderSettings, sender)
if err != nil {
return fmt.Errorf("failed to register sender [%s], err [%s]", senderSettings["type"], err.Error())
}
}
if notifier.config.SelfStateEnabled {
selfStateSettings := map[string]string{"type": selfStateSender}
if err = notifier.RegisterSender(selfStateSettings, &selfstate.Sender{Database: connector}); err != nil {
sender := selfstate.NewSender(notifier.logger, connector)
if err = notifier.RegisterSender(selfStateSettings, sender); err != nil {
notifier.logger.Warningf("failed to register selfstate sender: %s", err.Error())
}
}
Expand All @@ -101,10 +111,7 @@ func (notifier *StandardNotifier) RegisterSender(senderSettings map[string]strin
default:
senderIdent = senderSettings["type"]
}
err := sender.Init(senderSettings, notifier.logger, notifier.config.Location, notifier.config.DateTimeFormat)
if err != nil {
return fmt.Errorf("failed to initialize sender [%s], err [%s]", senderIdent, err.Error())
}

eventsChannel := make(chan NotificationPackage)
notifier.senders[senderIdent] = eventsChannel
notifier.metrics.SendersOkMetrics.RegisterMeter(senderIdent, getGraphiteSenderIdent(senderIdent), "sends_ok")
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (

"github.com/bwmarrin/discordgo"
"github.com/moira-alert/moira"
"github.com/moira-alert/moira/senders"
"github.com/moira-alert/moira/notifier/senders"
)

const (
Expand Down
File renamed without changes.
29 changes: 17 additions & 12 deletions senders/discord/init.go → notifier/senders/discord/sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ const (
workerName = "DiscordBot"
)

// Sender implements moira sender interface for discord
// Sender implements moira sender interface for Discord.
// Use NewSender to create instance.
kissken marked this conversation as resolved.
Show resolved Hide resolved
type Sender struct {
DataBase moira.Database
logger moira.Logger
Expand All @@ -26,25 +27,28 @@ type Sender struct {
botUserID string
}

// Init reads the yaml config
func (sender *Sender) Init(senderSettings map[string]string, logger moira.Logger, location *time.Location, dateTimeFormat string) error {
var err error
// NewSender creates Sender instance.
func NewSender(senderSettings map[string]string, logger moira.Logger, location *time.Location, db moira.Database) (*Sender, error) {
kissken marked this conversation as resolved.
Show resolved Hide resolved
token := senderSettings["token"]
if token == "" {
return fmt.Errorf("cannot read the discord token from the config")
return nil, fmt.Errorf("cannot read the discord token from the config")
}
sender.session, err = discordgo.New("Bot " + token)
session, err := discordgo.New("Bot " + token)
if err != nil {
return fmt.Errorf("error creating discord session: %s", err)
return nil, fmt.Errorf("error creating discord session: %s", err)
}
sender.logger = logger
sender.frontURI = senderSettings["front_uri"]
sender.location = location

sender := &Sender{
DataBase: db,
session: session,
logger: logger,
frontURI: senderSettings["front_uri"],
location: location,
}
handleMsg := func(s *discordgo.Session, m *discordgo.MessageCreate) {
channel, err := s.Channel(m.ChannelID)
if err != nil {
sender.logger.Errorf("error while getting the channel details: %s", err)
logger.Errorf("error while getting the channel details: %s", err)
}

msg, err := sender.getResponse(m, channel)
Expand All @@ -56,7 +60,8 @@ func (sender *Sender) Init(senderSettings map[string]string, logger moira.Logger
sender.session.AddHandler(handleMsg)

go sender.runBot()
return nil

return sender, nil
}

func (sender *Sender) runBot() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,30 @@ type MockLock struct {
moira.Lock
}

func (lock *MockLock) Acquire(stop <-chan struct{}) (lost <-chan struct{}, error error) {
func (lock *MockLock) Acquire(<-chan struct{}) (lost <-chan struct{}, error error) {
return lost, nil
}
func (db *MockDB) NewLock(name string, ttl time.Duration) moira.Lock {
func (db *MockDB) NewLock(string, time.Duration) moira.Lock {
return &MockLock{}
}

func TestInit(t *testing.T) {
func TestNewSender(t *testing.T) {
logger, _ := logging.ConfigureLog("stdout", "debug", "test", true)
location, _ := time.LoadLocation("UTC")
Convey("Init tests", t, func() {
sender := Sender{DataBase: &MockDB{}}
Convey("Empty map", func() {
err := sender.Init(map[string]string{}, logger, nil, "")
sender, err := NewSender(map[string]string{}, logger, nil, &MockDB{})
So(err, ShouldResemble, fmt.Errorf("cannot read the discord token from the config"))
So(sender, ShouldResemble, Sender{DataBase: &MockDB{}})
So(sender, ShouldBeNil)
})

Convey("Has settings", func() {
senderSettings := map[string]string{
"token": "123",
"front_uri": "http://moira.uri",
}
sender.Init(senderSettings, logger, location, "15:04") //nolint
sender, err := NewSender(senderSettings, logger, location, &MockDB{})
So(err, ShouldBeNil)
So(sender.frontURI, ShouldResemble, "http://moira.uri")
So(sender.session.Token, ShouldResemble, "Bot 123")
So(sender.logger, ShouldResemble, logger)
Expand Down
Loading