fluent-plugin-slack 0.5.5 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/README.md +20 -9
- data/VERSION +1 -1
- data/lib/fluent/plugin/out_buffered_slack.rb +38 -18
- data/lib/fluent/plugin/out_slack.rb +38 -18
- data/lib/fluent/plugin/slack_client.rb +7 -3
- data/test/plugin/test_out_slack.rb +215 -126
- data/test/plugin/test_slack_client.rb +112 -129
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 63a07a1d2026c16d55cd088092f69953404b202e
|
4
|
+
data.tar.gz: 33f8b2de136067d8e0e7adfa69457bb676d97eaa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 429287c6ea93b6a2af9371e7c50624142295be16a2e81e2ba27f3d293dc310eed431a0481f33b349c52384839db415401285f38ee7a4dbbcc778dc2f5017ad06
|
7
|
+
data.tar.gz: 50b5c8f83db6ef873cc448c85106b63e6dd7c6ff547f960701ec0634077d9539d09cbb5adfea347448c17982c538f87c5cfd37a44876eb5f90c2e91d43c3dfc6
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
## 0.6.0 (2015/04/02)
|
2
|
+
|
3
|
+
This version has impcompatibility with previous versions in default option values
|
4
|
+
|
5
|
+
Enhancements:
|
6
|
+
|
7
|
+
* Support `link_names` and `parse` option. `link_names` option is `true` as default
|
8
|
+
|
9
|
+
Changes:
|
10
|
+
|
11
|
+
* the default payload of Incoming Webhook was changed
|
12
|
+
* `color` is `nil` as default
|
13
|
+
* `icon_emoji` is `nil` as default
|
14
|
+
* `username` is `nil` as default
|
15
|
+
* `mrkdwn` is `true` as default
|
16
|
+
|
1
17
|
## 0.5.5 (2015/04/01)
|
2
18
|
|
3
19
|
Enhancements:
|
data/README.md
CHANGED
@@ -14,7 +14,6 @@ $ fluent-gem install fluent-plugin-slack
|
|
14
14
|
webhook_url https://hooks.slack.com/services/XXX/XXX/XXX
|
15
15
|
channel general
|
16
16
|
username sowasowa
|
17
|
-
color good
|
18
17
|
icon_emoji :ghost:
|
19
18
|
flush_interval 60s
|
20
19
|
</match>
|
@@ -51,7 +50,6 @@ fluent_logger.post('slack', {
|
|
51
50
|
token xoxb-XXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXX
|
52
51
|
channel general
|
53
52
|
username sowasowa
|
54
|
-
color good
|
55
53
|
icon_emoji :ghost:
|
56
54
|
flush_interval 60s
|
57
55
|
</match>
|
@@ -68,16 +66,18 @@ fluent_logger.post('slack', {
|
|
68
66
|
|parameter|description|default|
|
69
67
|
|---|---|---|
|
70
68
|
|webhook_url|Incoming Webhook URI (Required for Incoming Webhook mode). See https://api.slack.com/incoming-webhooks||
|
71
|
-
|slackbot_url|Slackbot URI (Required for Slackbot mode). See https://api.slack.com/slackbot. `username`, `color`, `icon_emoji`, `icon_url` are not available for this mode, but Desktop Notification via Highlight Words works with only this mode
|
69
|
+
|slackbot_url|Slackbot URI (Required for Slackbot mode). See https://api.slack.com/slackbot. NOTE: most of optional parameters such as `username`, `color`, `icon_emoji`, `icon_url`, and `title` are not available for this mode, but Desktop Notification via Highlight Words works with only this mode||
|
72
70
|
|token|Token for Web API (Required for Web API mode). See https://api.slack.com/web||
|
73
|
-
|username|name of bot|
|
74
|
-
|color|color to use
|
75
|
-
|icon_emoji|emoji to use as the icon. either of icon_emoji or icon_url can be specified
|
76
|
-
|icon_url|url to an image to use as the icon. either of icon_emoji or icon_url can be specified|nil|
|
77
|
-
|mrkdwn|enable formatting. see https://api.slack.com/docs/formatting|
|
71
|
+
|username|name of bot|nil|
|
72
|
+
|color|color to use such as `good` or `bad`. See `Color` section of https://api.slack.com/docs/attachments. NOTE: This parameter must **not** be specified to receive Desktop Notification via Mentions in cases of Incoming Webhook and Slack Web API|nil|
|
73
|
+
|icon_emoji|emoji to use as the icon. either of `icon_emoji` or `icon_url` can be specified|nil|
|
74
|
+
|icon_url|url to an image to use as the icon. either of `icon_emoji` or `icon_url` can be specified|nil|
|
75
|
+
|mrkdwn|enable formatting. see https://api.slack.com/docs/formatting|true|
|
76
|
+
|link_names|find and link channel names and usernames. NOTE: This parameter must be `true` to receive Desktop Notification via Mentions in cases of Incoming Webhook and Slack Web API|true|
|
77
|
+
|parse|change how messages are treated. `none` or `full` can be specified. See `Parsing mode` section of https://api.slack.com/docs/formatting|nil|
|
78
78
|
|channel|channel to send messages (without first '#')||
|
79
79
|
|channel_keys|keys used to format channel. %s will be replaced with value specified by channel_keys if this option is used|nil|
|
80
|
-
|title|title format. %s will be replaced with value specified by title_keys. title is created from the first appeared record on each tag|nil|
|
80
|
+
|title|title format. %s will be replaced with value specified by title_keys. title is created from the first appeared record on each tag. NOTE: This parameter must **not** be specified to receive Desktop Notification via Mentions in cases of Incoming Webhook and Slack Web API|nil|
|
81
81
|
|title_keys|keys used to format the title|nil|
|
82
82
|
|message|message format. %s will be replaced with value specified by message_keys|%s|
|
83
83
|
|message_keys|keys used to format messages|message|
|
@@ -97,6 +97,17 @@ fluent_logger.post('slack', {
|
|
97
97
|
|
98
98
|
`fluent-plugin-slack` is a kind of BufferedOutput plugin, so you can also use [Buffer Parameters](http://docs.fluentd.org/articles/out_exec#buffer-parameters).
|
99
99
|
|
100
|
+
## FAQ
|
101
|
+
|
102
|
+
### Desktop Notification seems not working?
|
103
|
+
|
104
|
+
Currently, slack.com has following limitations:
|
105
|
+
|
106
|
+
1. Desktop Notification via both Highlight Words and Mentions works only with Slackbot Remote Control
|
107
|
+
2. Desktop Notification via Mentions works for the `text` field if `link_names` parameter is specified in cases of Incoming Webhook and Slack Web API, that is,
|
108
|
+
* Desktop Notification does not work for the `attachments` filed (used in `color` and `title`)
|
109
|
+
* Desktop Notification via Highlight Words does not work for Incoming Webhook and Slack Web API anyway
|
110
|
+
|
100
111
|
## ChangeLog
|
101
112
|
|
102
113
|
See [CHANGELOG.md](CHANGELOG.md) for details.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.0
|
@@ -14,11 +14,13 @@ module Fluent
|
|
14
14
|
config_param :webhook_url, :string, default: nil # incoming webhook
|
15
15
|
config_param :slackbot_url, :string, default: nil # slackbot
|
16
16
|
config_param :token, :string, default: nil # api token
|
17
|
-
config_param :username, :string, default:
|
18
|
-
config_param :color, :string, default:
|
17
|
+
config_param :username, :string, default: nil
|
18
|
+
config_param :color, :string, default: nil
|
19
19
|
config_param :icon_emoji, :string, default: nil
|
20
20
|
config_param :icon_url, :string, default: nil
|
21
|
-
config_param :mrkdwn, :bool, default:
|
21
|
+
config_param :mrkdwn, :bool, default: true
|
22
|
+
config_param :link_names, :bool, default: true
|
23
|
+
config_param :parse, :string, default: nil
|
22
24
|
config_param :auto_channels_create, :bool, default: false
|
23
25
|
config_param :https_proxy, :string, default: nil
|
24
26
|
|
@@ -56,25 +58,19 @@ module Fluent
|
|
56
58
|
if @webhook_url.empty?
|
57
59
|
raise Fluent::ConfigError.new("`webhook_url` is an empty string")
|
58
60
|
end
|
59
|
-
# following default values are for old version compatibility
|
60
|
-
@title ||= '%s'
|
61
|
-
@title_keys ||= %w[tag]
|
62
|
-
@message ||= '[%s] %s'
|
63
|
-
@message_keys ||= %w[time message]
|
64
61
|
@slack = Fluent::SlackClient::IncomingWebhook.new(@webhook_url)
|
65
62
|
elsif @slackbot_url
|
66
63
|
if @slackbot_url.empty?
|
67
64
|
raise Fluent::ConfigError.new("`slackbot_url` is an empty string")
|
68
65
|
end
|
69
|
-
@
|
70
|
-
|
66
|
+
if @username or @color or @icon_emoji or @icon_url
|
67
|
+
log.warn "out_slack: `username`, `color`, `icon_emoji`, `icon_url` parameters are not available for Slackbot Remote Control"
|
68
|
+
end
|
71
69
|
@slack = Fluent::SlackClient::Slackbot.new(@slackbot_url)
|
72
70
|
elsif @token
|
73
71
|
if @token.empty?
|
74
72
|
raise Fluent::ConfigError.new("`token` is an empty string")
|
75
73
|
end
|
76
|
-
@message ||= '%s'
|
77
|
-
@message_keys ||= %w[message]
|
78
74
|
@slack = Fluent::SlackClient::WebApi.new
|
79
75
|
else
|
80
76
|
raise Fluent::ConfigError.new("One of `webhook_url` or `slackbot_url`, or `token` is required")
|
@@ -86,6 +82,8 @@ module Fluent
|
|
86
82
|
@slack.https_proxy = @https_proxy
|
87
83
|
end
|
88
84
|
|
85
|
+
@message ||= '%s'
|
86
|
+
@message_keys ||= %w[message]
|
89
87
|
begin
|
90
88
|
@message % (['1'] * @message_keys.length)
|
91
89
|
rescue ArgumentError
|
@@ -109,13 +107,16 @@ module Fluent
|
|
109
107
|
if @icon_emoji and @icon_url
|
110
108
|
raise Fluent::ConfigError, "either of `icon_emoji` or `icon_url` can be specified"
|
111
109
|
end
|
112
|
-
@icon_emoji ||= ':question:' unless @icon_url
|
113
110
|
|
114
111
|
if @mrkdwn
|
115
112
|
# Enable markdown for attachments. See https://api.slack.com/docs/formatting
|
116
113
|
@mrkdwn_in = %w[text fields]
|
117
114
|
end
|
118
115
|
|
116
|
+
if @parse and !%w[none full].include?(@parse)
|
117
|
+
raise Fluent::ConfigError, "`parse` must be either of `none` or `full`"
|
118
|
+
end
|
119
|
+
|
119
120
|
@post_message_opts = @auto_channels_create ? {auto_channels_create: true} : {}
|
120
121
|
end
|
121
122
|
|
@@ -142,6 +143,8 @@ module Fluent
|
|
142
143
|
def build_payloads(chunk)
|
143
144
|
if @title
|
144
145
|
build_title_payloads(chunk)
|
146
|
+
elsif @color
|
147
|
+
build_color_payloads(chunk)
|
145
148
|
else
|
146
149
|
build_plain_payloads(chunk)
|
147
150
|
end
|
@@ -150,9 +153,12 @@ module Fluent
|
|
150
153
|
def common_payload
|
151
154
|
return @common_payload if @common_payload
|
152
155
|
@common_payload = {}
|
153
|
-
@common_payload[:username] = @username
|
156
|
+
@common_payload[:username] = @username if @username
|
154
157
|
@common_payload[:icon_emoji] = @icon_emoji if @icon_emoji
|
155
158
|
@common_payload[:icon_url] = @icon_url if @icon_url
|
159
|
+
@common_payload[:mrkdwn] = @mrkdwn if @mrkdwn
|
160
|
+
@common_payload[:link_names] = @link_names if @link_names
|
161
|
+
@common_payload[:parse] = @parse if @parse
|
156
162
|
@common_payload[:token] = @token if @token
|
157
163
|
@common_payload
|
158
164
|
end
|
@@ -160,7 +166,8 @@ module Fluent
|
|
160
166
|
def common_attachment
|
161
167
|
return @common_attachment if @common_attachment
|
162
168
|
@common_attachment = {}
|
163
|
-
@common_attachment[:
|
169
|
+
@common_attachment[:color] = @color if @color
|
170
|
+
@common_attachment[:mrkdwn_in] = @mrkdwn_in if @mrkdwn_in
|
164
171
|
@common_attachment
|
165
172
|
end
|
166
173
|
|
@@ -179,7 +186,6 @@ module Fluent
|
|
179
186
|
{
|
180
187
|
channel: channel,
|
181
188
|
attachments: [{
|
182
|
-
:color => @color,
|
183
189
|
:fallback => fields.values.map(&:title).join(' '), # fallback is the message shown on popup
|
184
190
|
:fields => fields.values.map(&:to_h)
|
185
191
|
}.merge(common_attachment)],
|
@@ -187,7 +193,7 @@ module Fluent
|
|
187
193
|
end
|
188
194
|
end
|
189
195
|
|
190
|
-
def
|
196
|
+
def build_color_payloads(chunk)
|
191
197
|
messages = {}
|
192
198
|
chunk.msgpack_each do |tag, time, record|
|
193
199
|
channel = build_channel(record)
|
@@ -198,7 +204,6 @@ module Fluent
|
|
198
204
|
{
|
199
205
|
channel: channel,
|
200
206
|
attachments: [{
|
201
|
-
:color => @color,
|
202
207
|
:fallback => text,
|
203
208
|
:text => text,
|
204
209
|
}.merge(common_attachment)],
|
@@ -206,6 +211,21 @@ module Fluent
|
|
206
211
|
end
|
207
212
|
end
|
208
213
|
|
214
|
+
def build_plain_payloads(chunk)
|
215
|
+
messages = {}
|
216
|
+
chunk.msgpack_each do |tag, time, record|
|
217
|
+
channel = build_channel(record)
|
218
|
+
messages[channel] ||= ''
|
219
|
+
messages[channel] << "#{build_message(record)}\n"
|
220
|
+
end
|
221
|
+
messages.map do |channel, text|
|
222
|
+
{
|
223
|
+
channel: channel,
|
224
|
+
text: text,
|
225
|
+
}.merge(common_payload)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
209
229
|
def build_message(record)
|
210
230
|
values = fetch_keys(record, @message_keys)
|
211
231
|
@message % values
|
@@ -14,11 +14,13 @@ module Fluent
|
|
14
14
|
config_param :webhook_url, :string, default: nil # incoming webhook
|
15
15
|
config_param :slackbot_url, :string, default: nil # slackbot
|
16
16
|
config_param :token, :string, default: nil # api token
|
17
|
-
config_param :username, :string, default:
|
18
|
-
config_param :color, :string, default:
|
17
|
+
config_param :username, :string, default: nil
|
18
|
+
config_param :color, :string, default: nil
|
19
19
|
config_param :icon_emoji, :string, default: nil
|
20
20
|
config_param :icon_url, :string, default: nil
|
21
|
-
config_param :mrkdwn, :bool, default:
|
21
|
+
config_param :mrkdwn, :bool, default: true
|
22
|
+
config_param :link_names, :bool, default: true
|
23
|
+
config_param :parse, :string, default: nil
|
22
24
|
config_param :auto_channels_create, :bool, default: false
|
23
25
|
config_param :https_proxy, :string, default: nil
|
24
26
|
|
@@ -56,25 +58,19 @@ module Fluent
|
|
56
58
|
if @webhook_url.empty?
|
57
59
|
raise Fluent::ConfigError.new("`webhook_url` is an empty string")
|
58
60
|
end
|
59
|
-
# following default values are for old version compatibility
|
60
|
-
@title ||= '%s'
|
61
|
-
@title_keys ||= %w[tag]
|
62
|
-
@message ||= '[%s] %s'
|
63
|
-
@message_keys ||= %w[time message]
|
64
61
|
@slack = Fluent::SlackClient::IncomingWebhook.new(@webhook_url)
|
65
62
|
elsif @slackbot_url
|
66
63
|
if @slackbot_url.empty?
|
67
64
|
raise Fluent::ConfigError.new("`slackbot_url` is an empty string")
|
68
65
|
end
|
69
|
-
@
|
70
|
-
|
66
|
+
if @username or @color or @icon_emoji or @icon_url
|
67
|
+
log.warn "out_slack: `username`, `color`, `icon_emoji`, `icon_url` parameters are not available for Slackbot Remote Control"
|
68
|
+
end
|
71
69
|
@slack = Fluent::SlackClient::Slackbot.new(@slackbot_url)
|
72
70
|
elsif @token
|
73
71
|
if @token.empty?
|
74
72
|
raise Fluent::ConfigError.new("`token` is an empty string")
|
75
73
|
end
|
76
|
-
@message ||= '%s'
|
77
|
-
@message_keys ||= %w[message]
|
78
74
|
@slack = Fluent::SlackClient::WebApi.new
|
79
75
|
else
|
80
76
|
raise Fluent::ConfigError.new("One of `webhook_url` or `slackbot_url`, or `token` is required")
|
@@ -86,6 +82,8 @@ module Fluent
|
|
86
82
|
@slack.https_proxy = @https_proxy
|
87
83
|
end
|
88
84
|
|
85
|
+
@message ||= '%s'
|
86
|
+
@message_keys ||= %w[message]
|
89
87
|
begin
|
90
88
|
@message % (['1'] * @message_keys.length)
|
91
89
|
rescue ArgumentError
|
@@ -109,13 +107,16 @@ module Fluent
|
|
109
107
|
if @icon_emoji and @icon_url
|
110
108
|
raise Fluent::ConfigError, "either of `icon_emoji` or `icon_url` can be specified"
|
111
109
|
end
|
112
|
-
@icon_emoji ||= ':question:' unless @icon_url
|
113
110
|
|
114
111
|
if @mrkdwn
|
115
112
|
# Enable markdown for attachments. See https://api.slack.com/docs/formatting
|
116
113
|
@mrkdwn_in = %w[text fields]
|
117
114
|
end
|
118
115
|
|
116
|
+
if @parse and !%w[none full].include?(@parse)
|
117
|
+
raise Fluent::ConfigError, "`parse` must be either of `none` or `full`"
|
118
|
+
end
|
119
|
+
|
119
120
|
@post_message_opts = @auto_channels_create ? {auto_channels_create: true} : {}
|
120
121
|
end
|
121
122
|
|
@@ -142,6 +143,8 @@ module Fluent
|
|
142
143
|
def build_payloads(chunk)
|
143
144
|
if @title
|
144
145
|
build_title_payloads(chunk)
|
146
|
+
elsif @color
|
147
|
+
build_color_payloads(chunk)
|
145
148
|
else
|
146
149
|
build_plain_payloads(chunk)
|
147
150
|
end
|
@@ -150,9 +153,12 @@ module Fluent
|
|
150
153
|
def common_payload
|
151
154
|
return @common_payload if @common_payload
|
152
155
|
@common_payload = {}
|
153
|
-
@common_payload[:username] = @username
|
156
|
+
@common_payload[:username] = @username if @username
|
154
157
|
@common_payload[:icon_emoji] = @icon_emoji if @icon_emoji
|
155
158
|
@common_payload[:icon_url] = @icon_url if @icon_url
|
159
|
+
@common_payload[:mrkdwn] = @mrkdwn if @mrkdwn
|
160
|
+
@common_payload[:link_names] = @link_names if @link_names
|
161
|
+
@common_payload[:parse] = @parse if @parse
|
156
162
|
@common_payload[:token] = @token if @token
|
157
163
|
@common_payload
|
158
164
|
end
|
@@ -160,7 +166,8 @@ module Fluent
|
|
160
166
|
def common_attachment
|
161
167
|
return @common_attachment if @common_attachment
|
162
168
|
@common_attachment = {}
|
163
|
-
@common_attachment[:
|
169
|
+
@common_attachment[:color] = @color if @color
|
170
|
+
@common_attachment[:mrkdwn_in] = @mrkdwn_in if @mrkdwn_in
|
164
171
|
@common_attachment
|
165
172
|
end
|
166
173
|
|
@@ -179,7 +186,6 @@ module Fluent
|
|
179
186
|
{
|
180
187
|
channel: channel,
|
181
188
|
attachments: [{
|
182
|
-
:color => @color,
|
183
189
|
:fallback => fields.values.map(&:title).join(' '), # fallback is the message shown on popup
|
184
190
|
:fields => fields.values.map(&:to_h)
|
185
191
|
}.merge(common_attachment)],
|
@@ -187,7 +193,7 @@ module Fluent
|
|
187
193
|
end
|
188
194
|
end
|
189
195
|
|
190
|
-
def
|
196
|
+
def build_color_payloads(chunk)
|
191
197
|
messages = {}
|
192
198
|
chunk.msgpack_each do |tag, time, record|
|
193
199
|
channel = build_channel(record)
|
@@ -198,7 +204,6 @@ module Fluent
|
|
198
204
|
{
|
199
205
|
channel: channel,
|
200
206
|
attachments: [{
|
201
|
-
:color => @color,
|
202
207
|
:fallback => text,
|
203
208
|
:text => text,
|
204
209
|
}.merge(common_attachment)],
|
@@ -206,6 +211,21 @@ module Fluent
|
|
206
211
|
end
|
207
212
|
end
|
208
213
|
|
214
|
+
def build_plain_payloads(chunk)
|
215
|
+
messages = {}
|
216
|
+
chunk.msgpack_each do |tag, time, record|
|
217
|
+
channel = build_channel(record)
|
218
|
+
messages[channel] ||= ''
|
219
|
+
messages[channel] << "#{build_message(record)}\n"
|
220
|
+
end
|
221
|
+
messages.map do |channel, text|
|
222
|
+
{
|
223
|
+
channel: channel,
|
224
|
+
text: text,
|
225
|
+
}.merge(common_payload)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
209
229
|
def build_message(record)
|
210
230
|
values = fetch_keys(record, @message_keys)
|
211
231
|
@message % values
|
@@ -151,8 +151,12 @@ module Fluent
|
|
151
151
|
end
|
152
152
|
|
153
153
|
def encode_body(params = {})
|
154
|
-
|
155
|
-
|
154
|
+
return params[:text]if params[:text]
|
155
|
+
unless params[:attachments]
|
156
|
+
raise ArgumentError, 'params[:text] or params[:attachments] is required'
|
157
|
+
end
|
158
|
+
# handle params[:attachments]
|
159
|
+
attachment = Array(params[:attachments]).first # see only the first for now
|
156
160
|
# {
|
157
161
|
# attachments: [{
|
158
162
|
# text: "HERE",
|
@@ -168,7 +172,7 @@ module Fluent
|
|
168
172
|
# }]
|
169
173
|
# }
|
170
174
|
if text.nil? and attachment[:fields]
|
171
|
-
text = Array(attachment[:fields]).first[:value] #
|
175
|
+
text = Array(attachment[:fields]).first[:value] # see only the first for now
|
172
176
|
end
|
173
177
|
text
|
174
178
|
end
|
@@ -12,9 +12,23 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
12
12
|
|
13
13
|
CONFIG = %[
|
14
14
|
channel channel
|
15
|
-
|
15
|
+
webhook_url https://hooks.slack.com/services/XXXX/XXXX/XXX
|
16
16
|
]
|
17
17
|
|
18
|
+
def default_payload
|
19
|
+
{
|
20
|
+
channel: '#channel',
|
21
|
+
mrkdwn: true,
|
22
|
+
link_names: true,
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def default_attachment
|
27
|
+
{
|
28
|
+
mrkdwn_in: %w[text fields],
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
18
32
|
def create_driver(conf = CONFIG)
|
19
33
|
Fluent::Test::BufferedOutputTestDriver.new(Fluent::SlackOutput).configure(conf)
|
20
34
|
end
|
@@ -23,12 +37,15 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
23
37
|
def test_old_config
|
24
38
|
# default check
|
25
39
|
d = create_driver
|
26
|
-
assert_equal true,
|
27
|
-
assert_equal
|
28
|
-
assert_equal
|
29
|
-
assert_equal ':question:'
|
40
|
+
assert_equal true, d.instance.localtime
|
41
|
+
assert_equal nil, d.instance.username # 'fluentd' break lower version compatibility
|
42
|
+
assert_equal nil, d.instance.color # 'good' break lower version compatibility
|
43
|
+
assert_equal nil, d.instance.icon_emoji # ':question:' break lower version compatibility
|
44
|
+
assert_equal nil, d.instance.icon_url
|
45
|
+
assert_equal true, d.instance.mrkdwn
|
46
|
+
assert_equal true, d.instance.link_names
|
47
|
+
assert_equal nil, d.instance.parse
|
30
48
|
|
31
|
-
# incoming webhook endpoint was changed. api_key option should be ignored
|
32
49
|
assert_nothing_raised do
|
33
50
|
create_driver(CONFIG + %[api_key testtoken])
|
34
51
|
end
|
@@ -84,7 +101,9 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
84
101
|
assert_raise(Fluent::ConfigError) do
|
85
102
|
create_driver(CONFIG + %[channel %s %s\nchannel_keys foo])
|
86
103
|
end
|
104
|
+
end
|
87
105
|
|
106
|
+
def test_slack_configure
|
88
107
|
# One of webhook_url or slackbot_url, or token is required
|
89
108
|
assert_raise(Fluent::ConfigError) do
|
90
109
|
create_driver(%[channel foo])
|
@@ -146,7 +165,7 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
146
165
|
def test_icon_configure
|
147
166
|
# default
|
148
167
|
d = create_driver(CONFIG)
|
149
|
-
assert_equal
|
168
|
+
assert_equal nil, d.instance.icon_emoji
|
150
169
|
assert_equal nil, d.instance.icon_url
|
151
170
|
|
152
171
|
# either of icon_emoji or icon_url can be specified
|
@@ -165,28 +184,66 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
165
184
|
assert_equal @icon_url, d.instance.icon_url
|
166
185
|
end
|
167
186
|
|
168
|
-
def
|
187
|
+
def test_link_names_configure
|
169
188
|
# default
|
170
189
|
d = create_driver(CONFIG)
|
171
|
-
assert_equal
|
172
|
-
assert_equal Net::HTTP, d.instance.slack.proxy_class
|
190
|
+
assert_equal true, d.instance.link_names
|
173
191
|
|
174
|
-
#
|
175
|
-
d = create_driver(CONFIG + %[
|
176
|
-
assert_equal
|
177
|
-
|
192
|
+
# true
|
193
|
+
d = create_driver(CONFIG + %[link_names true])
|
194
|
+
assert_equal true, d.instance.link_names
|
195
|
+
|
196
|
+
# false
|
197
|
+
d = create_driver(CONFIG + %[link_names false])
|
198
|
+
assert_equal false, d.instance.link_names
|
199
|
+
end
|
200
|
+
|
201
|
+
def test_parse_configure
|
202
|
+
# default
|
203
|
+
d = create_driver(CONFIG)
|
204
|
+
assert_equal nil, d.instance.parse
|
205
|
+
|
206
|
+
# none
|
207
|
+
d = create_driver(CONFIG + %[parse none])
|
208
|
+
assert_equal 'none', d.instance.parse
|
209
|
+
|
210
|
+
# full
|
211
|
+
d = create_driver(CONFIG + %[parse full])
|
212
|
+
assert_equal 'full', d.instance.parse
|
213
|
+
|
214
|
+
# invalid
|
215
|
+
assert_raise(Fluent::ConfigError) do
|
216
|
+
d = create_driver(CONFIG + %[parse invalid])
|
217
|
+
end
|
178
218
|
end
|
179
219
|
|
180
220
|
def test_mrkwn_configure
|
181
221
|
# default
|
182
222
|
d = create_driver(CONFIG)
|
183
|
-
assert_equal
|
184
|
-
assert_equal
|
223
|
+
assert_equal true, d.instance.mrkdwn
|
224
|
+
assert_equal %w[text fields], d.instance.mrkdwn_in
|
185
225
|
|
186
|
-
#
|
226
|
+
# true
|
187
227
|
d = create_driver(CONFIG + %[mrkdwn true])
|
188
228
|
assert_equal true, d.instance.mrkdwn
|
189
229
|
assert_equal %w[text fields], d.instance.mrkdwn_in
|
230
|
+
|
231
|
+
# false
|
232
|
+
d = create_driver(CONFIG + %[mrkdwn false])
|
233
|
+
assert_equal false, d.instance.mrkdwn
|
234
|
+
assert_equal nil, d.instance.mrkdwn_in
|
235
|
+
end
|
236
|
+
|
237
|
+
def test_https_proxy_configure
|
238
|
+
# default
|
239
|
+
d = create_driver(CONFIG)
|
240
|
+
assert_equal nil, d.instance.slack.https_proxy
|
241
|
+
assert_equal Net::HTTP, d.instance.slack.proxy_class
|
242
|
+
|
243
|
+
# https_proxy
|
244
|
+
d = create_driver(CONFIG + %[https_proxy https://proxy.foo.bar:443])
|
245
|
+
assert_equal URI.parse('https://proxy.foo.bar:443'), d.instance.slack.https_proxy
|
246
|
+
assert_not_equal Net::HTTP, d.instance.slack.proxy_class # Net::HTTP.Proxy
|
190
247
|
end
|
191
248
|
|
192
249
|
def test_default_incoming_webhook
|
@@ -197,19 +254,9 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
197
254
|
assert_equal Fluent::SlackClient::IncomingWebhook, d.instance.slack.class
|
198
255
|
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
199
256
|
d.tag = 'test'
|
200
|
-
mock(d.instance.slack).post_message({
|
201
|
-
|
202
|
-
|
203
|
-
icon_emoji: ':question:',
|
204
|
-
attachments: [{
|
205
|
-
color: 'good',
|
206
|
-
fallback: 'test',
|
207
|
-
fields: [{
|
208
|
-
title: 'test',
|
209
|
-
value: "[07:00:00] sowawa1\n[07:00:00] sowawa2\n",
|
210
|
-
}],
|
211
|
-
}]
|
212
|
-
}, {})
|
257
|
+
mock(d.instance.slack).post_message(default_payload.merge({
|
258
|
+
text: "sowawa1\nsowawa2\n",
|
259
|
+
}), {})
|
213
260
|
with_timezone('Asia/Tokyo') do
|
214
261
|
d.emit({message: 'sowawa1'}, time)
|
215
262
|
d.emit({message: 'sowawa2'}, time)
|
@@ -225,16 +272,9 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
225
272
|
assert_equal Fluent::SlackClient::Slackbot, d.instance.slack.class
|
226
273
|
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
227
274
|
d.tag = 'test'
|
228
|
-
mock(d.instance.slack).post_message({
|
229
|
-
|
230
|
-
|
231
|
-
icon_emoji: ':question:',
|
232
|
-
attachments: [{
|
233
|
-
color: 'good',
|
234
|
-
fallback: "sowawa1\nsowawa2\n",
|
235
|
-
text: "sowawa1\nsowawa2\n",
|
236
|
-
}]
|
237
|
-
}, {})
|
275
|
+
mock(d.instance.slack).post_message(default_payload.merge({
|
276
|
+
text: "sowawa1\nsowawa2\n",
|
277
|
+
}), {})
|
238
278
|
with_timezone('Asia/Tokyo') do
|
239
279
|
d.emit({message: 'sowawa1'}, time)
|
240
280
|
d.emit({message: 'sowawa2'}, time)
|
@@ -250,17 +290,69 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
250
290
|
assert_equal Fluent::SlackClient::WebApi, d.instance.slack.class
|
251
291
|
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
252
292
|
d.tag = 'test'
|
253
|
-
mock(d.instance.slack).post_message({
|
254
|
-
token:
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
293
|
+
mock(d.instance.slack).post_message(default_payload.merge({
|
294
|
+
token: 'XX-XX-XX',
|
295
|
+
text: "sowawa1\nsowawa2\n",
|
296
|
+
}), {})
|
297
|
+
with_timezone('Asia/Tokyo') do
|
298
|
+
d.emit({message: 'sowawa1'}, time)
|
299
|
+
d.emit({message: 'sowawa2'}, time)
|
300
|
+
d.run
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
def test_title_payload
|
305
|
+
title = "mytitle"
|
306
|
+
d = create_driver(CONFIG + %[title #{title}])
|
307
|
+
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
308
|
+
d.tag = 'test'
|
309
|
+
# attachments field should be changed to show the title
|
310
|
+
mock(d.instance.slack).post_message(default_payload.merge({
|
311
|
+
attachments: [default_attachment.merge({
|
312
|
+
fallback: title,
|
313
|
+
fields: [
|
314
|
+
{
|
315
|
+
title: title,
|
316
|
+
value: "sowawa1\nsowawa2\n",
|
317
|
+
}
|
318
|
+
],
|
319
|
+
})]
|
320
|
+
}), {})
|
321
|
+
with_timezone('Asia/Tokyo') do
|
322
|
+
d.emit({message: 'sowawa1'}, time)
|
323
|
+
d.emit({message: 'sowawa2'}, time)
|
324
|
+
d.run
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
def test_color_payload
|
329
|
+
color = 'good'
|
330
|
+
d = create_driver(CONFIG + %[color #{color}])
|
331
|
+
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
332
|
+
d.tag = 'test'
|
333
|
+
# attachments field should be changed to show the title
|
334
|
+
mock(d.instance.slack).post_message(default_payload.merge({
|
335
|
+
attachments: [default_attachment.merge({
|
336
|
+
color: color,
|
260
337
|
fallback: "sowawa1\nsowawa2\n",
|
261
338
|
text: "sowawa1\nsowawa2\n",
|
262
|
-
}]
|
263
|
-
}, {})
|
339
|
+
})]
|
340
|
+
}), {})
|
341
|
+
with_timezone('Asia/Tokyo') do
|
342
|
+
d.emit({message: 'sowawa1'}, time)
|
343
|
+
d.emit({message: 'sowawa2'}, time)
|
344
|
+
d.run
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
def test_plain_payload
|
349
|
+
d = create_driver(CONFIG)
|
350
|
+
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
351
|
+
d.tag = 'test'
|
352
|
+
# attachments field should be changed to show the title
|
353
|
+
mock(d.instance.slack).post_message(default_payload.merge({
|
354
|
+
text: "sowawa1\nsowawa2\n",
|
355
|
+
}), {})
|
264
356
|
with_timezone('Asia/Tokyo') do
|
265
357
|
d.emit({message: 'sowawa1'}, time)
|
266
358
|
d.emit({message: 'sowawa2'}, time)
|
@@ -269,26 +361,21 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
269
361
|
end
|
270
362
|
|
271
363
|
def test_title_keys
|
272
|
-
d = create_driver(CONFIG + %[title %s\ntitle_keys tag])
|
364
|
+
d = create_driver(CONFIG + %[title [%s] %s\ntitle_keys time,tag])
|
273
365
|
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
274
366
|
d.tag = 'test'
|
275
367
|
# attachments field should be changed to show the title
|
276
|
-
mock(d.instance.slack).post_message({
|
277
|
-
|
278
|
-
|
279
|
-
username: 'fluentd',
|
280
|
-
icon_emoji: ':question:',
|
281
|
-
attachments: [{
|
282
|
-
color: 'good',
|
283
|
-
fallback: d.tag,
|
368
|
+
mock(d.instance.slack).post_message(default_payload.merge({
|
369
|
+
attachments: [default_attachment.merge({
|
370
|
+
fallback: "[07:00:00] #{d.tag}",
|
284
371
|
fields: [
|
285
372
|
{
|
286
|
-
title: d.tag,
|
373
|
+
title: "[07:00:00] #{d.tag}",
|
287
374
|
value: "sowawa1\nsowawa2\n",
|
288
375
|
}
|
289
376
|
],
|
290
|
-
}]
|
291
|
-
}, {})
|
377
|
+
})]
|
378
|
+
}), {})
|
292
379
|
with_timezone('Asia/Tokyo') do
|
293
380
|
d.emit({message: 'sowawa1'}, time)
|
294
381
|
d.emit({message: 'sowawa2'}, time)
|
@@ -297,20 +384,12 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
297
384
|
end
|
298
385
|
|
299
386
|
def test_message_keys
|
300
|
-
d = create_driver(CONFIG + %[message %s %s\nmessage_keys tag,message])
|
387
|
+
d = create_driver(CONFIG + %[message [%s] %s %s\nmessage_keys time,tag,message])
|
301
388
|
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
302
389
|
d.tag = 'test'
|
303
|
-
mock(d.instance.slack).post_message({
|
304
|
-
|
305
|
-
|
306
|
-
username: 'fluentd',
|
307
|
-
icon_emoji: ':question:',
|
308
|
-
attachments: [{
|
309
|
-
color: 'good',
|
310
|
-
fallback: "test sowawa1\ntest sowawa2\n",
|
311
|
-
text: "test sowawa1\ntest sowawa2\n",
|
312
|
-
}]
|
313
|
-
}, {})
|
390
|
+
mock(d.instance.slack).post_message(default_payload.merge({
|
391
|
+
text: "[07:00:00] test sowawa1\n[07:00:00] test sowawa2\n",
|
392
|
+
}), {})
|
314
393
|
with_timezone('Asia/Tokyo') do
|
315
394
|
d.emit({message: 'sowawa1'}, time)
|
316
395
|
d.emit({message: 'sowawa2'}, time)
|
@@ -322,28 +401,14 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
322
401
|
d = create_driver(CONFIG + %[channel %s\nchannel_keys channel])
|
323
402
|
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
324
403
|
d.tag = 'test'
|
325
|
-
mock(d.instance.slack).post_message({
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
text: "sowawa1\n",
|
334
|
-
}]
|
335
|
-
}, {})
|
336
|
-
mock(d.instance.slack).post_message({
|
337
|
-
token: 'XXX-XXX-XXX',
|
338
|
-
channel: '#channel2',
|
339
|
-
username: 'fluentd',
|
340
|
-
icon_emoji: ':question:',
|
341
|
-
attachments: [{
|
342
|
-
color: 'good',
|
343
|
-
fallback: "sowawa2\n",
|
344
|
-
text: "sowawa2\n",
|
345
|
-
}]
|
346
|
-
}, {})
|
404
|
+
mock(d.instance.slack).post_message(default_payload.merge({
|
405
|
+
channel: '#channel1',
|
406
|
+
text: "sowawa1\n",
|
407
|
+
}), {})
|
408
|
+
mock(d.instance.slack).post_message(default_payload.merge({
|
409
|
+
channel: '#channel2',
|
410
|
+
text: "sowawa2\n",
|
411
|
+
}), {})
|
347
412
|
with_timezone('Asia/Tokyo') do
|
348
413
|
d.emit({message: 'sowawa1', channel: 'channel1'}, time)
|
349
414
|
d.emit({message: 'sowawa2', channel: 'channel2'}, time)
|
@@ -355,17 +420,10 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
355
420
|
d = create_driver(CONFIG + %[icon_emoji :ghost:])
|
356
421
|
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
357
422
|
d.tag = 'test'
|
358
|
-
mock(d.instance.slack).post_message({
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
icon_emoji: ':ghost:',
|
363
|
-
attachments: [{
|
364
|
-
color: 'good',
|
365
|
-
fallback: "foo\n",
|
366
|
-
text: "foo\n",
|
367
|
-
}]
|
368
|
-
}, {})
|
423
|
+
mock(d.instance.slack).post_message(default_payload.merge({
|
424
|
+
icon_emoji: ':ghost:',
|
425
|
+
text: "foo\n",
|
426
|
+
}), {})
|
369
427
|
with_timezone('Asia/Tokyo') do
|
370
428
|
d.emit({message: 'foo'}, time)
|
371
429
|
d.run
|
@@ -376,17 +434,10 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
376
434
|
d = create_driver(CONFIG + %[icon_url #{@icon_url}])
|
377
435
|
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
378
436
|
d.tag = 'test'
|
379
|
-
mock(d.instance.slack).post_message({
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
icon_url: @icon_url,
|
384
|
-
attachments: [{
|
385
|
-
color: 'good',
|
386
|
-
fallback: "foo\n",
|
387
|
-
text: "foo\n",
|
388
|
-
}]
|
389
|
-
}, {})
|
437
|
+
mock(d.instance.slack).post_message(default_payload.merge({
|
438
|
+
icon_url: @icon_url,
|
439
|
+
text: "foo\n",
|
440
|
+
}), {})
|
390
441
|
with_timezone('Asia/Tokyo') do
|
391
442
|
d.emit({message: 'foo'}, time)
|
392
443
|
d.run
|
@@ -397,18 +448,56 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
397
448
|
d = create_driver(CONFIG + %[mrkdwn true])
|
398
449
|
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
399
450
|
d.tag = 'test'
|
400
|
-
mock(d.instance.slack).post_message({
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
451
|
+
mock(d.instance.slack).post_message(default_payload.merge({
|
452
|
+
mrkdwn: true,
|
453
|
+
text: "foo\n",
|
454
|
+
}), {})
|
455
|
+
with_timezone('Asia/Tokyo') do
|
456
|
+
d.emit({message: 'foo'}, time)
|
457
|
+
d.run
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
461
|
+
def test_mrkdwn_in
|
462
|
+
d = create_driver(CONFIG + %[mrkdwn true\ncolor good])
|
463
|
+
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
464
|
+
d.tag = 'test'
|
465
|
+
mock(d.instance.slack).post_message(default_payload.merge({
|
466
|
+
attachments: [default_attachment.merge({
|
467
|
+
color: "good",
|
407
468
|
fallback: "foo\n",
|
408
469
|
text: "foo\n",
|
409
470
|
mrkdwn_in: ["text", "fields"],
|
410
|
-
}]
|
411
|
-
}, {})
|
471
|
+
})]
|
472
|
+
}), {})
|
473
|
+
with_timezone('Asia/Tokyo') do
|
474
|
+
d.emit({message: 'foo'}, time)
|
475
|
+
d.run
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
479
|
+
def test_link_names
|
480
|
+
d = create_driver(CONFIG + %[link_names true])
|
481
|
+
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
482
|
+
d.tag = 'test'
|
483
|
+
mock(d.instance.slack).post_message(default_payload.merge({
|
484
|
+
link_names: true,
|
485
|
+
text: "foo\n",
|
486
|
+
}), {})
|
487
|
+
with_timezone('Asia/Tokyo') do
|
488
|
+
d.emit({message: 'foo'}, time)
|
489
|
+
d.run
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
def test_parse
|
494
|
+
d = create_driver(CONFIG + %[parse full])
|
495
|
+
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
496
|
+
d.tag = 'test'
|
497
|
+
mock(d.instance.slack).post_message(default_payload.merge({
|
498
|
+
parse: "full",
|
499
|
+
text: "foo\n",
|
500
|
+
}), {})
|
412
501
|
with_timezone('Asia/Tokyo') do
|
413
502
|
d.emit({message: 'foo'}, time)
|
414
503
|
d.run
|
@@ -10,10 +10,11 @@ require 'webrick/httpproxy'
|
|
10
10
|
# Create .env file with contents as:
|
11
11
|
#
|
12
12
|
# WEBHOOK_URL=https://hooks.slack.com/services/XXXX/YYYY/ZZZZ
|
13
|
-
#
|
13
|
+
# SLACKBOt_URL=https://xxxx.slack.com/services/hooks/slackbot?token=XXXX
|
14
|
+
# SLACK_API_TOKEN=XXXXX
|
14
15
|
#
|
15
16
|
Dotenv.load
|
16
|
-
if ENV['WEBHOOK_URL'] and ENV['SLACKBOT_URL'] and ENV['
|
17
|
+
if ENV['WEBHOOK_URL'] and ENV['SLACKBOT_URL'] and ENV['SLACK_API_TOKEN']
|
17
18
|
|
18
19
|
class TestProxyServer
|
19
20
|
def initialize
|
@@ -47,152 +48,148 @@ if ENV['WEBHOOK_URL'] and ENV['SLACKBOT_URL'] and ENV['TOKEN']
|
|
47
48
|
end
|
48
49
|
|
49
50
|
class SlackClientTest < Test::Unit::TestCase
|
51
|
+
class << self
|
52
|
+
attr_reader :proxy
|
53
|
+
|
54
|
+
def startup
|
55
|
+
@proxy = TestProxyServer.new.tap {|proxy| proxy.start }
|
56
|
+
end
|
57
|
+
|
58
|
+
def shutdown
|
59
|
+
@proxy.shutdown
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
50
63
|
def setup
|
51
64
|
super
|
52
65
|
@incoming = Fluent::SlackClient::IncomingWebhook.new(ENV['WEBHOOK_URL'])
|
53
66
|
@slackbot = Fluent::SlackClient::Slackbot.new(ENV['SLACKBOT_URL'])
|
54
67
|
@api = Fluent::SlackClient::WebApi.new
|
55
68
|
|
56
|
-
|
57
|
-
@incoming_proxy = Fluent::SlackClient::IncomingWebhook.new(ENV['WEBHOOK_URL'],
|
58
|
-
@slackbot_proxy = Fluent::SlackClient::Slackbot.new(ENV['SLACKBOT_URL'],
|
59
|
-
@api_proxy = Fluent::SlackClient::WebApi.new(nil,
|
69
|
+
proxy_url = self.class.proxy.proxy_url
|
70
|
+
@incoming_proxy = Fluent::SlackClient::IncomingWebhook.new(ENV['WEBHOOK_URL'], proxy_url)
|
71
|
+
@slackbot_proxy = Fluent::SlackClient::Slackbot.new(ENV['SLACKBOT_URL'], proxy_url)
|
72
|
+
@api_proxy = Fluent::SlackClient::WebApi.new(nil, proxy_url)
|
60
73
|
|
61
74
|
@icon_url = 'http://www.google.com/s2/favicons?domain=www.google.de'
|
62
75
|
end
|
63
76
|
|
64
|
-
def
|
65
|
-
|
77
|
+
def token(client)
|
78
|
+
client.is_a?(Fluent::SlackClient::IncomingWebhook) ? {} : {token: ENV['SLACK_API_TOKEN']}
|
66
79
|
end
|
67
80
|
|
68
|
-
def
|
69
|
-
|
81
|
+
def default_payload(client)
|
82
|
+
{
|
83
|
+
channel: '#general',
|
84
|
+
mrkdwn: true,
|
85
|
+
link_names: true,
|
86
|
+
}.merge!(token(client))
|
70
87
|
end
|
71
88
|
|
72
|
-
def
|
89
|
+
def default_attachment
|
90
|
+
{
|
91
|
+
mrkdwn_in: %w[text fields]
|
92
|
+
}
|
93
|
+
end
|
94
|
+
|
95
|
+
# Notification via Mention works for all three with plain text payload
|
96
|
+
def test_post_message_plain_payload_mention
|
73
97
|
[@incoming, @slackbot, @api].each do |slack|
|
74
98
|
assert_nothing_raised do
|
75
|
-
slack.post_message(
|
76
|
-
|
77
|
-
|
78
|
-
username: 'fluentd',
|
79
|
-
icon_emoji: ':question:',
|
80
|
-
attachments: [{
|
81
|
-
color: 'good',
|
82
|
-
fallback: "sowawa1\nsowawa2\n",
|
83
|
-
text: "sowawa1\nsowawa2\n",
|
84
|
-
}]
|
85
|
-
}.merge(token(slack))
|
86
|
-
)
|
99
|
+
slack.post_message(default_payload(slack).merge({
|
100
|
+
text: "#general @everyone\n",
|
101
|
+
}))
|
87
102
|
end
|
88
103
|
end
|
89
104
|
end
|
90
105
|
|
91
|
-
|
106
|
+
# Notification via Highlight Words works with only Slackbot with plain text payload
|
107
|
+
# NOTE: Please add `sowawa1` to Highlight Words
|
108
|
+
def test_post_message_plain_payload_highlight_words
|
92
109
|
[@incoming, @slackbot, @api].each do |slack|
|
93
110
|
assert_nothing_raised do
|
94
|
-
slack.post_message(
|
95
|
-
|
96
|
-
|
97
|
-
username: 'fluentd',
|
98
|
-
icon_emoji: ':question:',
|
99
|
-
attachments: [{
|
100
|
-
color: 'good',
|
101
|
-
fallback: 'test1 test2',
|
102
|
-
fields: [
|
103
|
-
{
|
104
|
-
title: 'test1',
|
105
|
-
value: "[07:00:00] sowawa1\n[07:00:00] sowawa2\n",
|
106
|
-
},
|
107
|
-
{
|
108
|
-
title: 'test2',
|
109
|
-
value: "[07:00:00] sowawa1\n[07:00:00] sowawa2\n",
|
110
|
-
},
|
111
|
-
],
|
112
|
-
}]
|
113
|
-
}.merge(token(slack))
|
114
|
-
)
|
111
|
+
slack.post_message(default_payload(slack).merge({
|
112
|
+
text: "sowawa1\n",
|
113
|
+
}))
|
115
114
|
end
|
116
115
|
end
|
117
116
|
end
|
118
117
|
|
119
|
-
|
120
|
-
|
118
|
+
# Notification via Mention does not work for attachments
|
119
|
+
def test_post_message_color_payload
|
120
|
+
[@incoming, @slackbot, @api].each do |slack|
|
121
121
|
assert_nothing_raised do
|
122
|
-
slack.post_message(
|
123
|
-
{
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
fallback: "sowawa1\nsowawa2\n",
|
130
|
-
text: "sowawa1\nsowawa2\n",
|
131
|
-
}]
|
132
|
-
}.merge(token(slack))
|
133
|
-
)
|
122
|
+
slack.post_message(default_payload(slack).merge({
|
123
|
+
attachments: [default_attachment.merge({
|
124
|
+
color: 'good',
|
125
|
+
fallback: "sowawa1\n@everyone\n",
|
126
|
+
text: "sowawa1\n@everyone\n",
|
127
|
+
})]
|
128
|
+
}))
|
134
129
|
end
|
135
130
|
end
|
136
131
|
end
|
137
132
|
|
138
|
-
|
139
|
-
|
133
|
+
# Notification via Mention does not work for attachments
|
134
|
+
def test_post_message_fields_payload
|
135
|
+
[@incoming, @slackbot, @api].each do |slack|
|
136
|
+
assert_nothing_raised do
|
137
|
+
slack.post_message(default_payload(slack).merge({
|
138
|
+
attachments: [default_attachment.merge({
|
139
|
+
color: 'good',
|
140
|
+
fallback: 'test1 test2',
|
141
|
+
fields: [
|
142
|
+
{
|
143
|
+
title: 'test1',
|
144
|
+
value: "[07:00:00] sowawa1\n[07:00:00] @everyone\n",
|
145
|
+
},
|
146
|
+
{
|
147
|
+
title: 'test2',
|
148
|
+
value: "[07:00:00] sowawa1\n[07:00:00] @everyone\n",
|
149
|
+
},
|
150
|
+
],
|
151
|
+
})]
|
152
|
+
}))
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_post_via_proxy
|
158
|
+
[@incoming_proxy, @slackbot_proxy, @api_proxy].each do |slack|
|
140
159
|
assert_nothing_raised do
|
141
|
-
slack.post_message(
|
142
|
-
{
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
fallback: "sowawa1\nsowawa2\n",
|
149
|
-
text: "sowawa1\nsowawa2\n",
|
150
|
-
}]
|
151
|
-
}.merge(token(slack))
|
152
|
-
)
|
160
|
+
slack.post_message(default_payload(slack).merge({
|
161
|
+
attachments: [default_attachment.merge({
|
162
|
+
color: 'good',
|
163
|
+
fallback: "sowawa1\n@everyone\n",
|
164
|
+
text: "sowawa1\n@everyone\n",
|
165
|
+
})]
|
166
|
+
}))
|
153
167
|
end
|
154
168
|
end
|
155
169
|
end
|
156
170
|
|
157
|
-
def
|
171
|
+
def test_post_message_username
|
158
172
|
[@incoming, @api].each do |slack|
|
159
173
|
assert_nothing_raised do
|
160
|
-
slack.post_message(
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
attachments: [{
|
165
|
-
color: 'good',
|
166
|
-
fallback: "plain *bold* _italic_ `preformat`\n", # mrkdwn not work
|
167
|
-
text: "plain *bold* _italic_ `preformat`\n",
|
168
|
-
mrkdwn_in: ['text', 'fields'],
|
169
|
-
}]
|
170
|
-
}.merge(token(slack))
|
171
|
-
)
|
174
|
+
slack.post_message(default_payload(slack).merge({
|
175
|
+
username: 'fluentd',
|
176
|
+
text: "#general @everyone\n",
|
177
|
+
}))
|
172
178
|
end
|
173
179
|
end
|
174
180
|
end
|
175
181
|
|
176
|
-
def
|
182
|
+
def test_post_message_icon_url
|
177
183
|
[@incoming, @api].each do |slack|
|
178
184
|
assert_nothing_raised do
|
179
|
-
slack.post_message(
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
{
|
188
|
-
title: 'plain *bold* _italic* `preformat`', # mrkdwn not work
|
189
|
-
value: "plain *bold* _italic* `preformat`\n",
|
190
|
-
},
|
191
|
-
],
|
192
|
-
mrkdwn_in: ['text', 'fields'],
|
193
|
-
}]
|
194
|
-
}.merge(token(slack))
|
195
|
-
)
|
185
|
+
slack.post_message(default_payload(slack).merge({
|
186
|
+
icon_url: @icon_url,
|
187
|
+
attachments: [default_attachment.merge({
|
188
|
+
color: 'good',
|
189
|
+
fallback: "sowawa1\n@everyone\n",
|
190
|
+
text: "sowawa1\n@everyone\n",
|
191
|
+
})]
|
192
|
+
}))
|
196
193
|
end
|
197
194
|
end
|
198
195
|
end
|
@@ -201,11 +198,9 @@ if ENV['WEBHOOK_URL'] and ENV['SLACKBOT_URL'] and ENV['TOKEN']
|
|
201
198
|
# but slack does not provide channels.delete API
|
202
199
|
def test_channels_create
|
203
200
|
begin
|
204
|
-
@api.channels_create(
|
205
|
-
|
206
|
-
|
207
|
-
}.merge(token(@api))
|
208
|
-
)
|
201
|
+
@api.channels_create(token(@api).merge({
|
202
|
+
name: '#test_channels_create',
|
203
|
+
}))
|
209
204
|
rescue Fluent::SlackClient::NameTakenError
|
210
205
|
end
|
211
206
|
end
|
@@ -214,17 +209,11 @@ if ENV['WEBHOOK_URL'] and ENV['SLACKBOT_URL'] and ENV['TOKEN']
|
|
214
209
|
# but slack does not provide channels.delete API
|
215
210
|
def test_auto_channels_create
|
216
211
|
assert_nothing_raised do
|
217
|
-
@api.post_message(
|
212
|
+
@api.post_message(default_payload(@api).merge(
|
218
213
|
{
|
219
|
-
channel:
|
220
|
-
|
221
|
-
|
222
|
-
attachments: [{
|
223
|
-
color: 'good',
|
224
|
-
fallback: "bar\n",
|
225
|
-
text: "bar\n",
|
226
|
-
}]
|
227
|
-
}.merge(token(@api)),
|
214
|
+
channel: '#test_auto_api',
|
215
|
+
text: "bar\n",
|
216
|
+
}),
|
228
217
|
{
|
229
218
|
auto_channels_create: true,
|
230
219
|
}
|
@@ -232,17 +221,11 @@ if ENV['WEBHOOK_URL'] and ENV['SLACKBOT_URL'] and ENV['TOKEN']
|
|
232
221
|
end
|
233
222
|
|
234
223
|
assert_nothing_raised do
|
235
|
-
@slackbot.post_message(
|
224
|
+
@slackbot.post_message(default_payload(@slackbot).merge(
|
236
225
|
{
|
237
|
-
channel:
|
238
|
-
|
239
|
-
|
240
|
-
attachments: [{
|
241
|
-
color: 'good',
|
242
|
-
fallback: "bar\n",
|
243
|
-
text: "bar\n",
|
244
|
-
}]
|
245
|
-
}.merge(token(@api)),
|
226
|
+
channel: '#test_auto_slackbot',
|
227
|
+
text: "bar\n",
|
228
|
+
}),
|
246
229
|
{
|
247
230
|
auto_channels_create: true,
|
248
231
|
}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-slack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keisuke SOGAWA
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-04-
|
12
|
+
date: 2015-04-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fluentd
|