Watcher: Support setting of markdown in attachments (elastic/x-pack-elasticsearch#1492)

Watcher: Support setting of markdown in attachments

This allows to set the `mrkdwn_in` array in slack attachments to specify which fields should contain markdown.
See https://api.slack.com/docs/message-formatting#message_formatting

This is mainly useful for the text and pretext fields in an attachment.

relates elastic/x-pack-elasticsearch#403

Original commit: elastic/x-pack-elasticsearch@ee4180e4bf
This commit is contained in:
Alexander Reelsen 2017-05-23 13:33:00 +02:00 committed by GitHub
parent e198845614
commit 521b7a1940
8 changed files with 237 additions and 233 deletions

View File

@ -222,6 +222,7 @@ xpack.notification.slack:
title: "X-Pack Notification" title: "X-Pack Notification"
title_link: "https://www.elastic.co/guide/en/x-pack/current/index.html" title_link: "https://www.elastic.co/guide/en/x-pack/current/index.html"
text: "One of your watches generated this notification." text: "One of your watches generated this notification."
mrkdwn_in: "pretext, text"
-------------------------------------------------- --------------------------------------------------
If you configure multiple Slack accounts, you either need to configure a default If you configure multiple Slack accounts, you either need to configure a default

View File

@ -18,6 +18,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
public class Attachment implements MessageElement { public class Attachment implements MessageElement {
@ -33,10 +34,11 @@ public class Attachment implements MessageElement {
final Field[] fields; final Field[] fields;
final String imageUrl; final String imageUrl;
final String thumbUrl; final String thumbUrl;
final String[] markdownSupportedFields;
public Attachment(String fallback, String color, String pretext, String authorName, String authorLink, public Attachment(String fallback, String color, String pretext, String authorName, String authorLink,
String authorIcon, String title, String titleLink, String text, Field[] fields, String authorIcon, String title, String titleLink, String text, Field[] fields,
String imageUrl, String thumbUrl) { String imageUrl, String thumbUrl, String[] markdownSupportedFields) {
this.fallback = fallback; this.fallback = fallback;
this.color = color; this.color = color;
@ -50,6 +52,7 @@ public class Attachment implements MessageElement {
this.fields = fields; this.fields = fields;
this.imageUrl = imageUrl; this.imageUrl = imageUrl;
this.thumbUrl = thumbUrl; this.thumbUrl = thumbUrl;
this.markdownSupportedFields = markdownSupportedFields;
} }
@Override @Override
@ -58,36 +61,19 @@ public class Attachment implements MessageElement {
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
Attachment that = (Attachment) o; Attachment that = (Attachment) o;
return Objects.equals(fallback, that.fallback) && Objects.equals(color, that.color) &&
if (fallback != null ? !fallback.equals(that.fallback) : that.fallback != null) return false; Objects.equals(pretext, that.pretext) && Objects.equals(authorName, that.authorName) &&
if (color != null ? !color.equals(that.color) : that.color != null) return false; Objects.equals(authorLink, that.authorLink) && Objects.equals(authorIcon, that.authorIcon) &&
if (pretext != null ? !pretext.equals(that.pretext) : that.pretext != null) return false; Objects.equals(title, that.title) && Objects.equals(titleLink, that.titleLink) &&
if (authorName != null ? !authorName.equals(that.authorName) : that.authorName != null) return false; Objects.equals(text, that.text) && Objects.equals(imageUrl, that.imageUrl) &&
if (authorLink != null ? !authorLink.equals(that.authorLink) : that.authorLink != null) return false; Objects.equals(thumbUrl, that.thumbUrl) &&
if (authorIcon != null ? !authorIcon.equals(that.authorIcon) : that.authorIcon != null) return false; Arrays.equals(markdownSupportedFields, that.markdownSupportedFields) && Arrays.equals(fields, that.fields);
if (title != null ? !title.equals(that.title) : that.title != null) return false;
if (titleLink != null ? !titleLink.equals(that.titleLink) : that.titleLink != null) return false;
if (text != null ? !text.equals(that.text) : that.text != null) return false;
if (!Arrays.equals(fields, that.fields)) return false;
if (imageUrl != null ? !imageUrl.equals(that.imageUrl) : that.imageUrl != null) return false;
return !(thumbUrl != null ? !thumbUrl.equals(that.thumbUrl) : that.thumbUrl != null);
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = fallback != null ? fallback.hashCode() : 0; return Objects.hash(fallback, color, pretext, authorName, authorLink, authorIcon, title, titleLink, text, fields, imageUrl,
result = 31 * result + (color != null ? color.hashCode() : 0); thumbUrl, markdownSupportedFields);
result = 31 * result + (pretext != null ? pretext.hashCode() : 0);
result = 31 * result + (authorName != null ? authorName.hashCode() : 0);
result = 31 * result + (authorLink != null ? authorLink.hashCode() : 0);
result = 31 * result + (authorIcon != null ? authorIcon.hashCode() : 0);
result = 31 * result + (title != null ? title.hashCode() : 0);
result = 31 * result + (titleLink != null ? titleLink.hashCode() : 0);
result = 31 * result + (text != null ? text.hashCode() : 0);
result = 31 * result + (fields != null ? Arrays.hashCode(fields) : 0);
result = 31 * result + (imageUrl != null ? imageUrl.hashCode() : 0);
result = 31 * result + (thumbUrl != null ? thumbUrl.hashCode() : 0);
return result;
} }
/** /**
@ -138,6 +124,13 @@ public class Attachment implements MessageElement {
if (thumbUrl != null) { if (thumbUrl != null) {
builder.field(XField.THUMB_URL.getPreferredName(), thumbUrl); builder.field(XField.THUMB_URL.getPreferredName(), thumbUrl);
} }
if (markdownSupportedFields != null) {
builder.startArray(XField.MARKDOWN_IN.getPreferredName());
for (String field : markdownSupportedFields) {
builder.value(field);
}
builder.endArray();
}
return builder.endObject(); return builder.endObject();
} }
@ -156,10 +149,13 @@ public class Attachment implements MessageElement {
final Field.Template[] fields; final Field.Template[] fields;
final TextTemplate imageUrl; final TextTemplate imageUrl;
final TextTemplate thumbUrl; final TextTemplate thumbUrl;
final TextTemplate[] markdownSupportedFields;
Template(TextTemplate fallback, TextTemplate color, TextTemplate pretext, TextTemplate authorName, Template(TextTemplate fallback, TextTemplate color, TextTemplate pretext, TextTemplate authorName,
TextTemplate authorLink, TextTemplate authorIcon, TextTemplate title, TextTemplate titleLink, TextTemplate authorLink, TextTemplate authorIcon, TextTemplate title, TextTemplate titleLink,
TextTemplate text, Field.Template[] fields, TextTemplate imageUrl, TextTemplate thumbUrl) { TextTemplate text, Field.Template[] fields, TextTemplate imageUrl, TextTemplate thumbUrl,
TextTemplate[] markdownSupportedFields) {
this.fallback = fallback; this.fallback = fallback;
this.color = color; this.color = color;
@ -173,6 +169,7 @@ public class Attachment implements MessageElement {
this.fields = fields; this.fields = fields;
this.imageUrl = imageUrl; this.imageUrl = imageUrl;
this.thumbUrl = thumbUrl; this.thumbUrl = thumbUrl;
this.markdownSupportedFields = markdownSupportedFields;
} }
public Attachment render(TextTemplateEngine engine, Map<String, Object> model, SlackMessageDefaults.AttachmentDefaults defaults) { public Attachment render(TextTemplateEngine engine, Map<String, Object> model, SlackMessageDefaults.AttachmentDefaults defaults) {
@ -194,8 +191,15 @@ public class Attachment implements MessageElement {
fields[i] = this.fields[i].render(engine, model, defaults.field); fields[i] = this.fields[i].render(engine, model, defaults.field);
} }
} }
String[] markdownFields = null;
if (this.markdownSupportedFields != null) {
markdownFields = new String[this.markdownSupportedFields.length];
for (int i = 0; i < markdownSupportedFields.length; i++) {
markdownFields[i] = engine.render(this.markdownSupportedFields[i], model);
}
}
return new Attachment(fallback, color, pretext, authorName, authorLink, authorIcon, title, titleLink, text, fields, imageUrl, return new Attachment(fallback, color, pretext, authorName, authorLink, authorIcon, title, titleLink, text, fields, imageUrl,
thumbUrl); thumbUrl, markdownFields);
} }
@Override @Override
@ -205,39 +209,20 @@ public class Attachment implements MessageElement {
Template template = (Template) o; Template template = (Template) o;
if (fallback != null ? !fallback.equals(template.fallback) : template.fallback != null) return false; return Objects.equals(fallback, template.fallback) && Objects.equals(color, template.color)
if (color != null ? !color.equals(template.color) : template.color != null) return false; && Objects.equals(pretext, template.pretext) && Objects.equals(authorName, template.authorName)
if (pretext != null ? !pretext.equals(template.pretext) : template.pretext != null) return false; && Objects.equals(authorLink, template.authorLink) && Objects.equals(authorIcon, template.authorIcon)
if (authorName != null ? !authorName.equals(template.authorName) : template.authorName != null) && Objects.equals(title, template.title) && Objects.equals(titleLink, template.titleLink)
return false; && Objects.equals(text, template.text) && Objects.equals(imageUrl, template.imageUrl)
if (authorLink != null ? !authorLink.equals(template.authorLink) : template.authorLink != null) && Objects.equals(thumbUrl, template.thumbUrl)
return false; && Arrays.equals(fields, template.fields)
if (authorIcon != null ? !authorIcon.equals(template.authorIcon) : template.authorIcon != null) && Arrays.equals(markdownSupportedFields, template.markdownSupportedFields);
return false;
if (title != null ? !title.equals(template.title) : template.title != null) return false;
if (titleLink != null ? !titleLink.equals(template.titleLink) : template.titleLink != null)
return false;
if (text != null ? !text.equals(template.text) : template.text != null) return false;
if (!Arrays.equals(fields, template.fields)) return false;
if (imageUrl != null ? !imageUrl.equals(template.imageUrl) : template.imageUrl != null) return false;
return !(thumbUrl != null ? !thumbUrl.equals(template.thumbUrl) : template.thumbUrl != null);
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = fallback != null ? fallback.hashCode() : 0; return Objects.hash(fallback, color, pretext, authorName, authorLink, authorIcon, title, titleLink, text, fields, imageUrl,
result = 31 * result + (color != null ? color.hashCode() : 0); thumbUrl, markdownSupportedFields);
result = 31 * result + (pretext != null ? pretext.hashCode() : 0);
result = 31 * result + (authorName != null ? authorName.hashCode() : 0);
result = 31 * result + (authorLink != null ? authorLink.hashCode() : 0);
result = 31 * result + (authorIcon != null ? authorIcon.hashCode() : 0);
result = 31 * result + (title != null ? title.hashCode() : 0);
result = 31 * result + (titleLink != null ? titleLink.hashCode() : 0);
result = 31 * result + (text != null ? text.hashCode() : 0);
result = 31 * result + (fields != null ? Arrays.hashCode(fields) : 0);
result = 31 * result + (imageUrl != null ? imageUrl.hashCode() : 0);
result = 31 * result + (thumbUrl != null ? thumbUrl.hashCode() : 0);
return result;
} }
@Override @Override
@ -283,6 +268,14 @@ public class Attachment implements MessageElement {
if (thumbUrl != null) { if (thumbUrl != null) {
builder.field(XField.THUMB_URL.getPreferredName(), thumbUrl, params); builder.field(XField.THUMB_URL.getPreferredName(), thumbUrl, params);
} }
if (markdownSupportedFields != null) {
builder.startArray(XField.MARKDOWN_IN.getPreferredName());
for (TextTemplate field : markdownSupportedFields) {
field.toXContent(builder, params);
}
builder.endArray();
}
return builder.endObject(); return builder.endObject();
} }
@ -300,6 +293,7 @@ public class Attachment implements MessageElement {
Field.Template[] fields = null; Field.Template[] fields = null;
TextTemplate imageUrl = null; TextTemplate imageUrl = null;
TextTemplate thumbUrl = null; TextTemplate thumbUrl = null;
TextTemplate[] markdownFields = null;
XContentParser.Token token = null; XContentParser.Token token = null;
String currentFieldName = null; String currentFieldName = null;
@ -403,6 +397,26 @@ public class Attachment implements MessageElement {
throw new ElasticsearchParseException("could not parse message attachment. failed to parse [{}] field", pe, throw new ElasticsearchParseException("could not parse message attachment. failed to parse [{}] field", pe,
XField.THUMB_URL); XField.THUMB_URL);
} }
} else if (XField.MARKDOWN_IN.match(currentFieldName)) {
if (token == XContentParser.Token.START_ARRAY) {
List<TextTemplate> list = new ArrayList<>();
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
try {
list.add(new TextTemplate(parser.text()));
} catch (ElasticsearchParseException pe) {
throw new ElasticsearchParseException("could not parse message attachment. failed to parse [{}] field",
pe, XField.MARKDOWN_IN);
}
}
markdownFields = list.toArray(new TextTemplate[list.size()]);
} else {
try {
markdownFields = new TextTemplate[]{ new TextTemplate(parser.text())};
} catch (ElasticsearchParseException pe) {
throw new ElasticsearchParseException("could not parse message attachment. failed to parse [{}] field", pe,
XField.MARKDOWN_IN);
}
}
} else { } else {
throw new ElasticsearchParseException("could not parse message attachment field. unexpected field [{}]", throw new ElasticsearchParseException("could not parse message attachment field. unexpected field [{}]",
currentFieldName); currentFieldName);
@ -425,7 +439,7 @@ public class Attachment implements MessageElement {
} }
} }
return new Template(fallback, color, pretext, authorName, authorLink, authorIcon, title, titleLink, text, fields, imageUrl, return new Template(fallback, color, pretext, authorName, authorLink, authorIcon, title, titleLink, text, fields, imageUrl,
thumbUrl); thumbUrl, markdownFields);
} }
@ -447,6 +461,7 @@ public class Attachment implements MessageElement {
private List<Field.Template> fields = new ArrayList<>(); private List<Field.Template> fields = new ArrayList<>();
private TextTemplate imageUrl; private TextTemplate imageUrl;
private TextTemplate thumbUrl; private TextTemplate thumbUrl;
private List<TextTemplate> markdownFields = new ArrayList<>();
private Builder() { private Builder() {
} }
@ -559,10 +574,17 @@ public class Attachment implements MessageElement {
return setThumbUrl(new TextTemplate(thumbUrl)); return setThumbUrl(new TextTemplate(thumbUrl));
} }
public Builder addMarkdownField(String name) {
this.markdownFields.add(new TextTemplate(name));
return this;
}
public Template build() { public Template build() {
Field.Template[] fields = this.fields.isEmpty() ? null : this.fields.toArray(new Field.Template[this.fields.size()]); Field.Template[] fields = this.fields.isEmpty() ? null : this.fields.toArray(new Field.Template[this.fields.size()]);
TextTemplate[] markdownFields =
this.markdownFields.isEmpty() ? null : this.markdownFields.toArray(new TextTemplate[this.markdownFields.size()]);
return new Template(fallback, color, pretext, authorName, authorLink, authorIcon, title, titleLink, text, fields, return new Template(fallback, color, pretext, authorName, authorLink, authorIcon, title, titleLink, text, fields,
imageUrl, thumbUrl); imageUrl, thumbUrl, markdownFields);
} }
} }
} }
@ -579,5 +601,7 @@ public class Attachment implements MessageElement {
ParseField FIELDS = new ParseField("fields"); ParseField FIELDS = new ParseField("fields");
ParseField IMAGE_URL = new ParseField("image_url"); ParseField IMAGE_URL = new ParseField("image_url");
ParseField THUMB_URL = new ParseField("thumb_url"); ParseField THUMB_URL = new ParseField("thumb_url");
ParseField MARKDOWN_IN = new ParseField("mrkdwn_in");
} }
} }

View File

@ -15,6 +15,7 @@ import org.elasticsearch.xpack.common.text.TextTemplateEngine;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.util.Map;
import java.util.Objects;
class Field implements MessageElement { class Field implements MessageElement {
@ -42,10 +43,7 @@ class Field implements MessageElement {
@Override @Override
public int hashCode() { public int hashCode() {
int result = title.hashCode(); return Objects.hash(title, value, isShort);
result = 31 * result + value.hashCode();
result = 31 * result + (isShort ? 1 : 0);
return result;
} }
@Override @Override

View File

@ -172,13 +172,7 @@ public class SlackMessage implements MessageElement {
@Override @Override
public int hashCode() { public int hashCode() {
int result = from != null ? from.hashCode() : 0; return Objects.hash(from, to, text, icon, attachments, dynamicAttachments);
result = 31 * result + (to != null ? Arrays.hashCode(to) : 0);
result = 31 * result + (text != null ? text.hashCode() : 0);
result = 31 * result + (icon != null ? icon.hashCode() : 0);
result = 31 * result + (attachments != null ? Arrays.hashCode(attachments) : 0);
result = 31 * result + (dynamicAttachments != null ? dynamicAttachments.hashCode() : 0);
return result;
} }
public SlackMessage render(String watchId, String actionId, TextTemplateEngine engine, Map<String, Object> model, public SlackMessage render(String watchId, String actionId, TextTemplateEngine engine, Map<String, Object> model,

View File

@ -8,14 +8,15 @@ package org.elasticsearch.xpack.notification.slack.message;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import java.util.Arrays; import java.util.Arrays;
import java.util.Objects;
public class SlackMessageDefaults { public class SlackMessageDefaults {
public static final String FROM_SETTING = SlackMessage.XField.FROM.getPreferredName(); private static final String FROM_SETTING = SlackMessage.XField.FROM.getPreferredName();
public static final String TO_SETTING = SlackMessage.XField.TO.getPreferredName(); private static final String TO_SETTING = SlackMessage.XField.TO.getPreferredName();
public static final String ICON_SETTING = SlackMessage.XField.ICON.getPreferredName(); private static final String ICON_SETTING = SlackMessage.XField.ICON.getPreferredName();
public static final String TEXT_SETTING = SlackMessage.XField.TEXT.getPreferredName(); private static final String TEXT_SETTING = SlackMessage.XField.TEXT.getPreferredName();
public static final String ATTACHMENT_SETTING = "attachment"; private static final String ATTACHMENT_SETTING = "attachment";
public final String from; public final String from;
public final String[] to; public final String[] to;
@ -47,41 +48,38 @@ public class SlackMessageDefaults {
@Override @Override
public int hashCode() { public int hashCode() {
int result = from != null ? from.hashCode() : 0; return Objects.hash(to, icon, text, attachment);
result = 31 * result + (to != null ? Arrays.hashCode(to) : 0);
result = 31 * result + (icon != null ? icon.hashCode() : 0);
result = 31 * result + (text != null ? text.hashCode() : 0);
result = 31 * result + (attachment != null ? attachment.hashCode() : 0);
return result;
} }
static class AttachmentDefaults { static class AttachmentDefaults {
public static final String FALLBACK_SETTING = Attachment.XField.FALLBACK.getPreferredName(); static final String FALLBACK_SETTING = Attachment.XField.FALLBACK.getPreferredName();
public static final String COLOR_SETTING = Attachment.XField.COLOR.getPreferredName(); static final String COLOR_SETTING = Attachment.XField.COLOR.getPreferredName();
public static final String PRETEXT_SETTING = Attachment.XField.PRETEXT.getPreferredName(); static final String PRETEXT_SETTING = Attachment.XField.PRETEXT.getPreferredName();
public static final String AUTHOR_NAME_SETTING = Attachment.XField.AUTHOR_NAME.getPreferredName(); static final String AUTHOR_NAME_SETTING = Attachment.XField.AUTHOR_NAME.getPreferredName();
public static final String AUTHOR_LINK_SETTING = Attachment.XField.AUTHOR_LINK.getPreferredName(); static final String AUTHOR_LINK_SETTING = Attachment.XField.AUTHOR_LINK.getPreferredName();
public static final String AUTHOR_ICON_SETTING = Attachment.XField.AUTHOR_ICON.getPreferredName(); static final String AUTHOR_ICON_SETTING = Attachment.XField.AUTHOR_ICON.getPreferredName();
public static final String TITLE_SETTING = Attachment.XField.TITLE.getPreferredName(); static final String TITLE_SETTING = Attachment.XField.TITLE.getPreferredName();
public static final String TITLE_LINK_SETTING = Attachment.XField.TITLE_LINK.getPreferredName(); static final String TITLE_LINK_SETTING = Attachment.XField.TITLE_LINK.getPreferredName();
public static final String TEXT_SETTING = Attachment.XField.TEXT.getPreferredName(); static final String TEXT_SETTING = Attachment.XField.TEXT.getPreferredName();
public static final String IMAGE_URL_SETTING = Attachment.XField.IMAGE_URL.getPreferredName(); static final String IMAGE_URL_SETTING = Attachment.XField.IMAGE_URL.getPreferredName();
public static final String THUMB_URL_SETTING = Attachment.XField.THUMB_URL.getPreferredName(); static final String THUMB_URL_SETTING = Attachment.XField.THUMB_URL.getPreferredName();
public static final String FIELD_SETTING = "field"; static final String MARKDOWN_IN_SETTING = Attachment.XField.MARKDOWN_IN.getPreferredName();
static final String FIELD_SETTING = "field";
public final String fallback; final String fallback;
public final String color; final String color;
public final String pretext; final String pretext;
public final String authorName; final String authorName;
public final String authorLink; final String authorLink;
public final String authorIcon; final String authorIcon;
public final String title; final String title;
public final String titleLink; final String titleLink;
public final String text; final String text;
public final String imageUrl; final String imageUrl;
public final String thumbUrl; final String thumbUrl;
public final FieldDefaults field; final String[] markdownSupportedFields;
final FieldDefaults field;
AttachmentDefaults(Settings settings) { AttachmentDefaults(Settings settings) {
fallback = settings.get(FALLBACK_SETTING, null); fallback = settings.get(FALLBACK_SETTING, null);
@ -95,6 +93,7 @@ public class SlackMessageDefaults {
text = settings.get(TEXT_SETTING, null); text = settings.get(TEXT_SETTING, null);
imageUrl = settings.get(IMAGE_URL_SETTING, null); imageUrl = settings.get(IMAGE_URL_SETTING, null);
thumbUrl = settings.get(THUMB_URL_SETTING, null); thumbUrl = settings.get(THUMB_URL_SETTING, null);
markdownSupportedFields = settings.getAsArray(MARKDOWN_IN_SETTING, null);
field = new FieldDefaults(settings.getAsSettings(FIELD_SETTING)); field = new FieldDefaults(settings.getAsSettings(FIELD_SETTING));
} }
@ -105,46 +104,30 @@ public class SlackMessageDefaults {
AttachmentDefaults that = (AttachmentDefaults) o; AttachmentDefaults that = (AttachmentDefaults) o;
if (fallback != null ? !fallback.equals(that.fallback) : that.fallback != null) return false; return Objects.equals(fallback, that.fallback) && Objects.equals(color, that.color) &&
if (color != null ? !color.equals(that.color) : that.color != null) return false; Objects.equals(pretext, that.pretext) && Objects.equals(authorName, that.authorName) &&
if (pretext != null ? !pretext.equals(that.pretext) : that.pretext != null) return false; Objects.equals(authorLink, that.authorLink) && Objects.equals(authorIcon, that.authorIcon) &&
if (authorName != null ? !authorName.equals(that.authorName) : that.authorName != null) return false; Objects.equals(title, that.title) && Objects.equals(titleLink, that.titleLink) &&
if (authorLink != null ? !authorLink.equals(that.authorLink) : that.authorLink != null) return false; Objects.equals(text, that.text) && Objects.equals(imageUrl, that.imageUrl) &&
if (authorIcon != null ? !authorIcon.equals(that.authorIcon) : that.authorIcon != null) return false; Objects.equals(thumbUrl, that.thumbUrl) && Objects.equals(field, that.field) &&
if (title != null ? !title.equals(that.title) : that.title != null) return false; Arrays.equals(markdownSupportedFields, that.markdownSupportedFields);
if (titleLink != null ? !titleLink.equals(that.titleLink) : that.titleLink != null) return false;
if (text != null ? !text.equals(that.text) : that.text != null) return false;
if (imageUrl != null ? !imageUrl.equals(that.imageUrl) : that.imageUrl != null) return false;
if (thumbUrl != null ? !thumbUrl.equals(that.thumbUrl) : that.thumbUrl != null) return false;
return !(field != null ? !field.equals(that.field) : that.field != null);
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = fallback != null ? fallback.hashCode() : 0; return Objects.hash(fallback, color, pretext, authorName, authorLink, authorIcon, title, titleLink, text, imageUrl,
result = 31 * result + (color != null ? color.hashCode() : 0); thumbUrl, field, markdownSupportedFields);
result = 31 * result + (pretext != null ? pretext.hashCode() : 0);
result = 31 * result + (authorName != null ? authorName.hashCode() : 0);
result = 31 * result + (authorLink != null ? authorLink.hashCode() : 0);
result = 31 * result + (authorIcon != null ? authorIcon.hashCode() : 0);
result = 31 * result + (title != null ? title.hashCode() : 0);
result = 31 * result + (titleLink != null ? titleLink.hashCode() : 0);
result = 31 * result + (text != null ? text.hashCode() : 0);
result = 31 * result + (imageUrl != null ? imageUrl.hashCode() : 0);
result = 31 * result + (thumbUrl != null ? thumbUrl.hashCode() : 0);
result = 31 * result + (field != null ? field.hashCode() : 0);
return result;
} }
static class FieldDefaults { static class FieldDefaults {
public static final String TITLE_SETTING = Field.XField.TITLE.getPreferredName(); static final String TITLE_SETTING = Field.XField.TITLE.getPreferredName();
public static final String VALUE_SETTING = Field.XField.VALUE.getPreferredName(); static final String VALUE_SETTING = Field.XField.VALUE.getPreferredName();
public static final String SHORT_SETTING = Field.XField.SHORT.getPreferredName(); static final String SHORT_SETTING = Field.XField.SHORT.getPreferredName();
public final String title; final String title;
public final String value; final String value;
public final Boolean isShort; final Boolean isShort;
FieldDefaults(Settings settings) { FieldDefaults(Settings settings) {
title = settings.get(TITLE_SETTING, null); title = settings.get(TITLE_SETTING, null);
@ -159,17 +142,12 @@ public class SlackMessageDefaults {
FieldDefaults that = (FieldDefaults) o; FieldDefaults that = (FieldDefaults) o;
if (title != null ? !title.equals(that.title) : that.title != null) return false; return Objects.equals(title, that.title) && Objects.equals(value, that.value) && Objects.equals(isShort, that.isShort);
if (value != null ? !value.equals(that.value) : that.value != null) return false;
return !(isShort != null ? !isShort.equals(that.isShort) : that.isShort != null);
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = title != null ? title.hashCode() : 0; return Objects.hash(title, value, isShort);
result = 31 * result + (value != null ? value.hashCode() : 0);
result = 31 * result + (isShort != null ? isShort.hashCode() : 0);
return result;
} }
} }
} }

View File

@ -11,6 +11,7 @@ import org.elasticsearch.test.ESTestCase;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
public class SlackMessageDefaultsTests extends ESTestCase { public class SlackMessageDefaultsTests extends ESTestCase {
public void testConstructor() throws Exception { public void testConstructor() throws Exception {
Settings settings = randomSettings(); Settings settings = randomSettings();
SlackMessageDefaults defaults = new SlackMessageDefaults(settings); SlackMessageDefaults defaults = new SlackMessageDefaults(settings);
@ -32,6 +33,7 @@ public class SlackMessageDefaultsTests extends ESTestCase {
assertThat(defaults.attachment.field.title, is(settings.get("attachment.field.title", null))); assertThat(defaults.attachment.field.title, is(settings.get("attachment.field.title", null)));
assertThat(defaults.attachment.field.value, is(settings.get("attachment.field.value", null))); assertThat(defaults.attachment.field.value, is(settings.get("attachment.field.value", null)));
assertThat(defaults.attachment.field.isShort, is(settings.getAsBoolean("attachment.field.short", null))); assertThat(defaults.attachment.field.isShort, is(settings.getAsBoolean("attachment.field.short", null)));
assertThat(defaults.attachment.markdownSupportedFields, is(settings.getAsArray("attachment.mrkdwn_in", null)));
} }
public static Settings randomSettings() { public static Settings randomSettings() {
@ -94,6 +96,13 @@ public class SlackMessageDefaultsTests extends ESTestCase {
if (randomBoolean()) { if (randomBoolean()) {
settings.put("attachment.field.short", randomBoolean()); settings.put("attachment.field.short", randomBoolean());
} }
if (randomBoolean()) {
if (randomBoolean()) {
settings.putArray("attachment.mrkdwn_in", "foo", "bar");
} else {
settings.put("attachment.mrkdwn_in", "foo,bar");
}
}
return settings.build(); return settings.build();
} }
} }

View File

@ -16,6 +16,7 @@ import org.elasticsearch.xpack.watcher.test.MockTextTemplateEngine;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -23,10 +24,12 @@ import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.arrayContaining;
import static org.hamcrest.Matchers.arrayContainingInAnyOrder;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
public class SlackMessageTests extends ESTestCase { public class SlackMessageTests extends ESTestCase {
public void testToXContent() throws Exception { public void testToXContent() throws Exception {
String from = randomBoolean() ? null : randomAlphaOfLength(10); String from = randomBoolean() ? null : randomAlphaOfLength(10);
String[] to = rarely() ? null : new String[randomIntBetween(0, 2)]; String[] to = rarely() ? null : new String[randomIntBetween(0, 2)];
@ -57,8 +60,9 @@ public class SlackMessageTests extends ESTestCase {
} }
String imageUrl = randomBoolean() ? null : randomAlphaOfLength(10); String imageUrl = randomBoolean() ? null : randomAlphaOfLength(10);
String thumbUrl = randomBoolean() ? null : randomAlphaOfLength(10); String thumbUrl = randomBoolean() ? null : randomAlphaOfLength(10);
String[] markdownFields = randomBoolean() ? null : new String[]{"pretext"};
attachments[i] = new Attachment(fallback, color, pretext, authorName, authorLink, authorIcon, title, titleLink, attachments[i] = new Attachment(fallback, color, pretext, authorName, authorLink, authorIcon, title, titleLink,
attachmentText, fields, imageUrl, thumbUrl); attachmentText, fields, imageUrl, thumbUrl, markdownFields);
} }
} }
@ -154,6 +158,7 @@ public class SlackMessageTests extends ESTestCase {
Field[] fields = null; Field[] fields = null;
String imageUrl = null; String imageUrl = null;
String thumbUrl = null; String thumbUrl = null;
String[] markdownSupportedFields = null;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) { if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName(); currentFieldName = parser.currentName();
@ -200,10 +205,16 @@ public class SlackMessageTests extends ESTestCase {
imageUrl = parser.text(); imageUrl = parser.text();
} else if ("thumb_url".equals(currentFieldName)) { } else if ("thumb_url".equals(currentFieldName)) {
thumbUrl = parser.text(); thumbUrl = parser.text();
} else if ("mrkdwn_in".equals(currentFieldName)) {
List<String> data = new ArrayList<>();
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
data.add(parser.text());
}
markdownSupportedFields = data.toArray(new String[]{});
} }
} }
list.add(new Attachment(fallback, color, pretext, authorName, authorLink, authorIcon, title, titleLink, list.add(new Attachment(fallback, color, pretext, authorName, authorLink, authorIcon, title, titleLink,
attachmentText, fields, imageUrl, thumbUrl)); attachmentText, fields, imageUrl, thumbUrl, markdownSupportedFields));
} }
attachments = list.toArray(new Attachment[list.size()]); attachments = list.toArray(new Attachment[list.size()]);
} }
@ -327,9 +338,16 @@ public class SlackMessageTests extends ESTestCase {
} }
jsonBuilder.endArray(); jsonBuilder.endArray();
} }
TextTemplate[] markdownSupportedFields = null;
if (randomBoolean()) {
jsonBuilder.startArray("mrkdwn_in");
jsonBuilder.value("pretext");
jsonBuilder.endArray();
markdownSupportedFields = new TextTemplate[] { new TextTemplate("pretext") };
}
jsonBuilder.endObject(); jsonBuilder.endObject();
attachments[i] = new Attachment.Template(fallback, color, pretext, authorName, authorLink, authorIcon, title, attachments[i] = new Attachment.Template(fallback, color, pretext, authorName, authorLink, authorIcon, title,
titleLink, attachmentText, fields, imageUrl, thumbUrl); titleLink, attachmentText, fields, imageUrl, thumbUrl, markdownSupportedFields);
} }
jsonBuilder.endArray(); jsonBuilder.endArray();
} }
@ -395,46 +413,7 @@ public class SlackMessageTests extends ESTestCase {
if (randomBoolean()) { if (randomBoolean()) {
int count = randomIntBetween(0, 3); int count = randomIntBetween(0, 3);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
Attachment.Template.Builder attachmentBuilder = Attachment.Template.builder(); Attachment.Template.Builder attachmentBuilder = createRandomAttachmentTemplateBuilder();
if (randomBoolean()) {
attachmentBuilder.setAuthorName(randomAlphaOfLength(10));
if (randomBoolean()) {
attachmentBuilder.setAuthorIcon(randomAlphaOfLength(10));
}
if (randomBoolean()) {
attachmentBuilder.setAuthorLink(randomAlphaOfLength(10));
}
}
if (randomBoolean()) {
attachmentBuilder.setColor(randomAlphaOfLength(10));
}
if (randomBoolean()) {
attachmentBuilder.setFallback(randomAlphaOfLength(10));
}
if (randomBoolean()) {
attachmentBuilder.setImageUrl(randomAlphaOfLength(10));
}
if (randomBoolean()) {
attachmentBuilder.setPretext(randomAlphaOfLength(10));
}
if (randomBoolean()) {
attachmentBuilder.setThumbUrl(randomAlphaOfLength(10));
}
if (randomBoolean()) {
attachmentBuilder.setTitle(randomAlphaOfLength(10));
if (randomBoolean()) {
attachmentBuilder.setTitleLink(randomAlphaOfLength(10));
}
}
if (randomBoolean()) {
attachmentBuilder.setText(randomAlphaOfLength(10));
}
if (randomBoolean()) {
int fieldCount = randomIntBetween(0, 3);
for (int j = 0; j < fieldCount; j++) {
attachmentBuilder.addField(randomAlphaOfLength(10), randomAlphaOfLength(10), randomBoolean());
}
}
templateBuilder.addAttachments(attachmentBuilder); templateBuilder.addAttachments(attachmentBuilder);
} }
} }
@ -504,11 +483,21 @@ public class SlackMessageTests extends ESTestCase {
is(fieldTemplate.isShort != null ? fieldTemplate.isShort : defaults.attachment.field.isShort)); is(fieldTemplate.isShort != null ? fieldTemplate.isShort : defaults.attachment.field.isShort));
} }
} }
if (attachmentTemplate.markdownSupportedFields == null) {
assertThat(attachment.markdownSupportedFields, nullValue());
} else {
for (int j = 0; j < attachmentTemplate.markdownSupportedFields.length; j++) {
String[] templateMarkdownSupportFields = Arrays.stream(attachmentTemplate.markdownSupportedFields)
.map(TextTemplate::getTemplate).toArray(String[]::new);
assertThat(attachment.markdownSupportedFields, arrayContainingInAnyOrder(templateMarkdownSupportFields));
}
}
} }
} }
} }
static void writeFieldIfNotNull(XContentBuilder builder, String field, Object value) throws IOException { private static void writeFieldIfNotNull(XContentBuilder builder, String field, Object value) throws IOException {
if (value != null) { if (value != null) {
builder.field(field, value); builder.field(field, value);
} }
@ -535,50 +524,62 @@ public class SlackMessageTests extends ESTestCase {
if (randomBoolean()) { if (randomBoolean()) {
int count = randomIntBetween(0, 3); int count = randomIntBetween(0, 3);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
Attachment.Template.Builder attachmentBuilder = Attachment.Template.builder(); Attachment.Template.Builder attachmentBuilder = createRandomAttachmentTemplateBuilder();
if (randomBoolean()) {
attachmentBuilder.setAuthorName(randomAlphaOfLength(10));
if (randomBoolean()) {
attachmentBuilder.setAuthorIcon(randomAlphaOfLength(10));
}
if (randomBoolean()) {
attachmentBuilder.setAuthorLink(randomAlphaOfLength(10));
}
}
if (randomBoolean()) {
attachmentBuilder.setColor(randomAlphaOfLength(10));
}
if (randomBoolean()) {
attachmentBuilder.setFallback(randomAlphaOfLength(10));
}
if (randomBoolean()) {
attachmentBuilder.setImageUrl(randomAlphaOfLength(10));
}
if (randomBoolean()) {
attachmentBuilder.setPretext(randomAlphaOfLength(10));
}
if (randomBoolean()) {
attachmentBuilder.setThumbUrl(randomAlphaOfLength(10));
}
if (randomBoolean()) {
attachmentBuilder.setTitle(randomAlphaOfLength(10));
if (randomBoolean()) {
attachmentBuilder.setTitleLink(randomAlphaOfLength(10));
}
}
if (randomBoolean()) {
attachmentBuilder.setText(randomAlphaOfLength(10));
}
if (randomBoolean()) {
int fieldCount = randomIntBetween(0, 3);
for (int j = 0; j < fieldCount; j++) {
attachmentBuilder.addField(randomAlphaOfLength(10), randomAlphaOfLength(10), randomBoolean());
}
}
templateBuilder.addAttachments(attachmentBuilder); templateBuilder.addAttachments(attachmentBuilder);
} }
} }
return templateBuilder.build(); return templateBuilder.build();
} }
private static Attachment.Template.Builder createRandomAttachmentTemplateBuilder() {
Attachment.Template.Builder attachmentBuilder = Attachment.Template.builder();
if (randomBoolean()) {
attachmentBuilder.setAuthorName(randomAlphaOfLength(10));
if (randomBoolean()) {
attachmentBuilder.setAuthorIcon(randomAlphaOfLength(10));
}
if (randomBoolean()) {
attachmentBuilder.setAuthorLink(randomAlphaOfLength(10));
}
}
if (randomBoolean()) {
attachmentBuilder.setColor(randomAlphaOfLength(10));
}
if (randomBoolean()) {
attachmentBuilder.setFallback(randomAlphaOfLength(10));
}
if (randomBoolean()) {
attachmentBuilder.setImageUrl(randomAlphaOfLength(10));
}
if (randomBoolean()) {
attachmentBuilder.setPretext(randomAlphaOfLength(10));
}
if (randomBoolean()) {
attachmentBuilder.setThumbUrl(randomAlphaOfLength(10));
}
if (randomBoolean()) {
attachmentBuilder.setTitle(randomAlphaOfLength(10));
if (randomBoolean()) {
attachmentBuilder.setTitleLink(randomAlphaOfLength(10));
}
}
if (randomBoolean()) {
attachmentBuilder.setText(randomAlphaOfLength(10));
}
if (randomBoolean()) {
int fieldCount = randomIntBetween(0, 3);
for (int j = 0; j < fieldCount; j++) {
attachmentBuilder.addField(randomAlphaOfLength(10), randomAlphaOfLength(10), randomBoolean());
}
}
if (randomBoolean()) {
attachmentBuilder.addMarkdownField(randomAlphaOfLength(10));
if (randomBoolean()) {
attachmentBuilder.addMarkdownField(randomAlphaOfLength(10));
}
}
return attachmentBuilder;
}
} }

View File

@ -63,8 +63,8 @@ public class SlackServiceTests extends AbstractWatcherIntegrationTestCase {
public void testSendMessage() throws Exception { public void testSendMessage() throws Exception {
SlackService service = getInstanceFromMaster(SlackService.class); SlackService service = getInstanceFromMaster(SlackService.class);
Attachment[] attachments = new Attachment[] { Attachment[] attachments = new Attachment[] {
new Attachment("fallback", randomFrom("good", "warning", "danger"), "pretext", "author_name", null, null, new Attachment("fallback", randomFrom("good", "warning", "danger"), "pretext `code` *bold*", "author_name", null, null,
"title", null, "_text", null, null, null) "title", null, "_text `code` *bold*", null, null, null, new String[] { "text", "pretext" })
}; };
SlackMessage message = new SlackMessage( SlackMessage message = new SlackMessage(
"SlackServiceTests", "SlackServiceTests",
@ -87,8 +87,7 @@ public class SlackServiceTests extends AbstractWatcherIntegrationTestCase {
builder.prettyPrint(); builder.prettyPrint();
sentMessage.toXContent(builder, EMPTY_PARAMS); sentMessage.toXContent(builder, EMPTY_PARAMS);
final String messageDescription = builder.string(); final String messageDescription = builder.string();
logger.warn("failed to send message. full message description: \n" logger.warn("failed to send message. full message description: \n" + messageDescription, e);
+ messageDescription, e);
throw e; throw e;
} }
} }