Skip to content

Commit 6a1dacb

Browse files
authored
CHAOSPLT-751: Add a slackUserEmail field to spec.reporting (#983)
* Added slack email field to reporting * made slack channel optional * revised logic of buildSlackMessage * small logic change to email parsing * added another error check * added test cases
1 parent 2bcf8da commit 6a1dacb

File tree

8 files changed

+474
-46
lines changed

8 files changed

+474
-46
lines changed

api/v1beta1/disruption_types.go

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -124,25 +124,40 @@ type Reporting struct {
124124
// It's expected to follow slack naming conventions https://api.slack.com/methods/conversations.create#naming or slack channel ID format
125125
// +kubebuilder:validation:MaxLength=80
126126
// +kubebuilder:validation:Pattern=(^[a-z0-9-_]+$)|(^C[A-Z0-9]+$)
127-
// +kubebuilder:validation:Required
128-
SlackChannel string `json:"slackChannel,omitempty" chaos_validate:"required"`
127+
SlackChannel string `json:"slackChannel,omitempty"`
129128
// Purpose determines contextual informations about the disruption
130129
// a brief context to determines disruption goal
131130
// +kubebuilder:validation:MinLength=10
132-
// +kubebuilder:validation:Required
133131
Purpose string `json:"purpose,omitempty"`
134132
// MinNotificationType is the minimal notification type we want to receive informations for
135133
// In order of importance it's Info, Success, Warning, Error
136134
// Default level is considered Success, meaning all info will be ignored
137135
MinNotificationType eventtypes.NotificationType `json:"minNotificationType,omitempty"`
136+
// SlackUserEmail is the email of the user to send reporting information to
137+
// +kubebuilder:validation:MaxLength=320
138+
SlackUserEmail string `json:"slackUserEmail,omitempty" chaos_validate:"email"`
138139
}
139140

140141
func (r *Reporting) Explain() string {
141-
return fmt.Sprintf("While the disruption is ongoing, it will send slack messages for every event of severity %s or higher, "+
142-
"to the slack channel with the ID (not name) %s, mentioning the purpose \"%s\"",
143-
r.MinNotificationType,
144-
r.SlackChannel,
145-
r.Purpose)
142+
parts := []string{"While the disruption is ongoing, it will send Slack messages"}
143+
144+
if r.MinNotificationType != "" {
145+
parts = append(parts, fmt.Sprintf("for every event of severity %s or higher", r.MinNotificationType))
146+
}
147+
148+
if r.SlackChannel != "" {
149+
parts = append(parts, fmt.Sprintf("to the Slack channel with the ID (not name) %s", r.SlackChannel))
150+
}
151+
152+
if r.SlackUserEmail != "" {
153+
parts = append(parts, fmt.Sprintf("and user %s", r.SlackUserEmail))
154+
}
155+
156+
if r.Purpose != "" {
157+
parts = append(parts, fmt.Sprintf("mentioning the purpose \"%s\"", r.Purpose))
158+
}
159+
160+
return strings.Join(parts, ", ") + "."
146161
}
147162

148163
// EmbeddedChaosAPI includes the library so it can be statically exported to chaosli

chart/templates/generated/chaos.datadoghq.com_disruptioncrons.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,10 @@ spec:
535535
maxLength: 80
536536
pattern: (^[a-z0-9-_]+$)|(^C[A-Z0-9]+$)
537537
type: string
538+
slackUserEmail:
539+
description: SlackUserEmail is the email of the user to send reporting information to
540+
maxLength: 320
541+
type: string
538542
type: object
539543
selector:
540544
additionalProperties:
@@ -654,6 +658,10 @@ spec:
654658
maxLength: 80
655659
pattern: (^[a-z0-9-_]+$)|(^C[A-Z0-9]+$)
656660
type: string
661+
slackUserEmail:
662+
description: SlackUserEmail is the email of the user to send reporting information to
663+
maxLength: 320
664+
type: string
657665
type: object
658666
schedule:
659667
description: The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.

chart/templates/generated/chaos.datadoghq.com_disruptionrollouts.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,10 @@ spec:
536536
maxLength: 80
537537
pattern: (^[a-z0-9-_]+$)|(^C[A-Z0-9]+$)
538538
type: string
539+
slackUserEmail:
540+
description: SlackUserEmail is the email of the user to send reporting information to
541+
maxLength: 320
542+
type: string
539543
type: object
540544
selector:
541545
additionalProperties:

chart/templates/generated/chaos.datadoghq.com_disruptions.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,10 @@ spec:
526526
maxLength: 80
527527
pattern: (^[a-z0-9-_]+$)|(^C[A-Z0-9]+$)
528528
type: string
529+
slackUserEmail:
530+
description: SlackUserEmail is the email of the user to send reporting information to
531+
maxLength: 320
532+
type: string
529533
type: object
530534
selector:
531535
additionalProperties:

eventnotifier/slack/slack.go

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ type slackMessage struct {
4141
BodyText string
4242
BodyBlock slack.SectionBlock
4343
InfoBlocks []*slack.TextBlockObject
44-
UserInfo authv1.UserInfo
44+
UserEmail string
4545
}
4646

4747
type NotifierSlackConfig struct {
@@ -180,16 +180,16 @@ func (n *Notifier) notifyForDisruptionCron(disruptionCron *v1beta1.DisruptionCro
180180
}
181181

182182
func (n *Notifier) sendMessageToUserChannel(slackMsg slackMessage, logger *zap.SugaredLogger) error {
183-
emailAddr, err := mail.ParseAddress(slackMsg.UserInfo.Username)
183+
emailAddr, err := mail.ParseAddress(slackMsg.UserEmail)
184184
if err != nil {
185-
logger.Infow("username could not be parsed as an email address", "err", err, "username", slackMsg.UserInfo.Username)
185+
logger.Infow("username could not be parsed as an email address", "err", err, "username", slackMsg.UserEmail)
186186

187187
return nil
188188
}
189189

190190
p1, err := n.client.GetUserByEmail(emailAddr.Address)
191191
if err != nil {
192-
logger.Warnw("user not found", "userAddress", emailAddr.Address, "error", err)
192+
logger.Warnw("user not found", "userAddress", slackMsg.UserEmail, "error", err)
193193

194194
return nil
195195
}
@@ -199,8 +199,8 @@ func (n *Notifier) sendMessageToUserChannel(slackMsg slackMessage, logger *zap.S
199199

200200
func (n *Notifier) sendMessageToChannel(slackChannel string, slackMsg slackMessage) error {
201201
userName := infoNotAvailable
202-
if slackMsg.UserInfo.Username != "" {
203-
userName = slackMsg.UserInfo.Username
202+
if slackMsg.UserEmail != "" {
203+
userName = slackMsg.UserEmail
204204
}
205205

206206
_, _, err := n.client.PostMessage(slackChannel,
@@ -228,28 +228,45 @@ func (n *Notifier) buildSlackMessage(obj client.Object, event corev1.Event, noti
228228
infoBlocks := n.buildSlackBlocks(obj, notifType, reporting)
229229

230230
var (
231-
userInfo authv1.UserInfo
232-
err error
231+
userEmail string
232+
userInfo authv1.UserInfo
233+
err error
233234
)
234235

235236
switch d := obj.(type) {
236237
case *v1beta1.Disruption:
238+
if nil != d.Spec.Reporting && d.Spec.Reporting.SlackUserEmail != "" {
239+
userEmail = d.Spec.Reporting.SlackUserEmail
240+
}
241+
237242
userInfo, err = d.UserInfo()
238243
case *v1beta1.DisruptionCron:
244+
if nil != d.Spec.Reporting && d.Spec.Reporting.SlackUserEmail != "" {
245+
userEmail = d.Spec.Reporting.SlackUserEmail
246+
}
247+
239248
userInfo, err = d.UserInfo()
240249
}
241250

242251
if err != nil {
243252
logger.Warnw("unable to retrieve user info", "error", err)
244253
}
245254

255+
// initiates the fallback mechanism incase SlackUserEmail is empty or an invalid input
256+
_, err = mail.ParseAddress(userEmail)
257+
if err != nil {
258+
logger.Infow("the slack user email is not a valid email address, fall back to userInfo", "err", err, "username", userEmail)
259+
260+
userEmail = userInfo.Username // falls back to userInfo username
261+
}
262+
246263
return slackMessage{
247264
HeaderText: headerText,
248265
HeaderBlock: *headerBlock,
249266
BodyText: bodyText,
250267
BodyBlock: *bodyBlock,
251268
InfoBlocks: infoBlocks,
252-
UserInfo: userInfo,
269+
UserEmail: userEmail,
253270
UserName: fmt.Sprintf("%s Status Bot", obj.GetObjectKind().GroupVersionKind().Kind),
254271
}
255272
}

0 commit comments

Comments
 (0)