fluent-plugin-slack 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +7 -0
- data/CHANGELOG.md +13 -0
- data/README.md +8 -3
- data/Rakefile +6 -1
- data/VERSION +1 -1
- data/example.conf +17 -0
- data/fluent-plugin-slack.gemspec +2 -2
- data/lib/fluent/plugin/out_buffered_slack.rb +24 -16
- data/lib/fluent/plugin/out_slack.rb +24 -16
- data/lib/fluent/plugin/slack_client.rb +86 -48
- data/lib/fluent/plugin/slack_client/error.rb +24 -0
- data/test.sh +2 -0
- data/test/plugin/test_out_slack.rb +27 -12
- data/test/plugin/test_slack_client.rb +37 -2
- metadata +11 -4
- data/AUTHORS +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 63fd1c619f76e7bb3df9b2ff11e69af43e23f810
|
4
|
+
data.tar.gz: 8fd2eb0e8790c71c8689ae88e42f8a4bae3f1d3b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf331ec94a09e572f2aa1c958842634195dad9078cc7fbf86813c121d88ddeb69568617663cf2012151646c52c6ec64203f95b3738348937bc0b8a417c6da976
|
7
|
+
data.tar.gz: c16e8a479300bc03539232a4d76d172d7eaa8c0d0e640612424fa483f2b7abd4510de6a3fee5b55d0eb2b70a395cc1a65d2425e3eb62c0e7a1058d9be3418d66
|
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
## 0.5.1 (2015/03/27)
|
2
|
+
|
3
|
+
Enhancements:
|
4
|
+
|
5
|
+
* Support `auto_channels_create` option to automatically create channels.
|
6
|
+
|
7
|
+
## 0.5.0 (2015/03/22)
|
8
|
+
|
9
|
+
Enhancements:
|
10
|
+
|
11
|
+
* Support `message` and `message_keys` options
|
12
|
+
* Support `title` and `title_keys` options
|
13
|
+
* Support `channel_keys` options to dynamically change channels
|
data/README.md
CHANGED
@@ -26,7 +26,7 @@ fluent_logger.post('slack', {
|
|
26
26
|
})
|
27
27
|
```
|
28
28
|
|
29
|
-
# Usage (
|
29
|
+
# Usage (Web API)
|
30
30
|
|
31
31
|
```apache
|
32
32
|
<match slack>
|
@@ -50,8 +50,8 @@ fluent_logger.post('slack', {
|
|
50
50
|
|
51
51
|
|parameter|description|default|
|
52
52
|
|---|---|---|
|
53
|
-
|
|
54
|
-
|token|Token for
|
53
|
+
|webhook_url|Incoming Webhook URI (Required for Incoming Webhook mode)||
|
54
|
+
|token|Token for Web API (Required for Web API mode)||
|
55
55
|
|username|name of bot|fluentd|
|
56
56
|
|color|color to use|good|
|
57
57
|
|icon_emoji|emoji to use as the icon|`:question:`|
|
@@ -61,6 +61,7 @@ fluent_logger.post('slack', {
|
|
61
61
|
|title_keys|keys used to format the title|nil|
|
62
62
|
|message|message format. %s will be replaced with value specified by message_keys|%s|
|
63
63
|
|message_keys|keys used to format messages|message|
|
64
|
+
|auto_channels_create|Create channels if not exist. Available only with Web API mode, and a token for Normal User is required (Bot User can not create channels. See https://api.slack.com/bot-users)|false|
|
64
65
|
|
65
66
|
`fluent-plugin-slack` uses `SetTimeKeyMixin` and `SetTagKeyMixin`, so you can also use:
|
66
67
|
|
@@ -75,6 +76,10 @@ fluent_logger.post('slack', {
|
|
75
76
|
|
76
77
|
`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).
|
77
78
|
|
79
|
+
## ChangeLog
|
80
|
+
|
81
|
+
See [CHANGELOG.md](CHANGELOG.md) for details.
|
82
|
+
|
78
83
|
# Contributors
|
79
84
|
|
80
85
|
- [@sonots](https://github.com/sonots)
|
data/Rakefile
CHANGED
@@ -7,5 +7,10 @@ Rake::TestTask.new(:test) do |test|
|
|
7
7
|
test.pattern = 'test/**/test_*.rb'
|
8
8
|
test.verbose = true
|
9
9
|
end
|
10
|
-
|
11
10
|
task :default => :test
|
11
|
+
|
12
|
+
desc 'Open an irb session preloaded with the gem library'
|
13
|
+
task :console do
|
14
|
+
sh 'irb -rubygems -I lib'
|
15
|
+
end
|
16
|
+
task :c => :console
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.1
|
data/example.conf
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
<source>
|
2
|
+
type forward
|
3
|
+
</source>
|
4
|
+
|
5
|
+
<match tag>
|
6
|
+
type slack
|
7
|
+
token "#{ENV['TOKEN']}"
|
8
|
+
username fluentd
|
9
|
+
color good
|
10
|
+
icon_emoji :ghost:
|
11
|
+
channel general
|
12
|
+
message %s %s
|
13
|
+
message_keys tag,message
|
14
|
+
title %s %s
|
15
|
+
title_keys tag,message
|
16
|
+
flush_interval 1s # slack API has limit as a post / sec
|
17
|
+
</match>
|
data/fluent-plugin-slack.gemspec
CHANGED
@@ -7,8 +7,8 @@ Gem::Specification.new do |gem|
|
|
7
7
|
gem.homepage = "https://github.com/sowawa/fluent-plugin-slack"
|
8
8
|
gem.summary = gem.description
|
9
9
|
gem.version = File.read("VERSION").strip
|
10
|
-
gem.authors = ["Keisuke SOGAWA"]
|
11
|
-
gem.email = "keisuke.sogawa@gmail.com"
|
10
|
+
gem.authors = ["Keisuke SOGAWA", "Naotoshi Seo"]
|
11
|
+
gem.email = ["keisuke.sogawa@gmail.com", "sonots@gmail.com"]
|
12
12
|
gem.has_rdoc = false
|
13
13
|
gem.files = `git ls-files`.split("\n")
|
14
14
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
@@ -11,22 +11,23 @@ module Fluent
|
|
11
11
|
config_set_default :include_time_key, true
|
12
12
|
config_set_default :include_tag_key, true
|
13
13
|
|
14
|
-
config_param :webhook_url,
|
15
|
-
config_param :token,
|
16
|
-
config_param :username,
|
17
|
-
config_param :color,
|
18
|
-
config_param :icon_emoji,
|
19
|
-
|
20
|
-
|
21
|
-
config_param :
|
14
|
+
config_param :webhook_url, :string, default: nil # incoming webhook
|
15
|
+
config_param :token, :string, default: nil # api token
|
16
|
+
config_param :username, :string, default: 'fluentd'
|
17
|
+
config_param :color, :string, default: 'good'
|
18
|
+
config_param :icon_emoji, :string, default: ':question:'
|
19
|
+
config_param :auto_channels_create, :bool, default: false
|
20
|
+
|
21
|
+
config_param :channel, :string
|
22
|
+
config_param :channel_keys, default: nil do |val|
|
22
23
|
val.split(',')
|
23
24
|
end
|
24
|
-
config_param :title,
|
25
|
-
config_param :title_keys,
|
25
|
+
config_param :title, :string, default: nil
|
26
|
+
config_param :title_keys, default: nil do |val|
|
26
27
|
val.split(',')
|
27
28
|
end
|
28
|
-
config_param :message,
|
29
|
-
config_param :message_keys,
|
29
|
+
config_param :message, :string, default: nil
|
30
|
+
config_param :message_keys, default: nil do |val|
|
30
31
|
val.split(',')
|
31
32
|
end
|
32
33
|
|
@@ -48,19 +49,24 @@ module Fluent
|
|
48
49
|
@channel = '#' + @channel unless @channel.start_with?('#')
|
49
50
|
|
50
51
|
if @webhook_url
|
52
|
+
if @webhook_url.empty?
|
53
|
+
raise Fluent::ConfigError.new("`webhook_url` is an empty string")
|
54
|
+
end
|
51
55
|
# following default values are for old version compatibility
|
52
56
|
@title ||= '%s'
|
53
57
|
@title_keys ||= %w[tag]
|
54
58
|
@message ||= '[%s] %s'
|
55
59
|
@message_keys ||= %w[time message]
|
56
60
|
@slack = Fluent::SlackClient::IncomingWebhook.new(@webhook_url)
|
57
|
-
|
58
|
-
|
59
|
-
raise Fluent::ConfigError.new("`token` is
|
61
|
+
elsif @token
|
62
|
+
if @token.empty?
|
63
|
+
raise Fluent::ConfigError.new("`token` is an empty string")
|
60
64
|
end
|
61
65
|
@message ||= '%s'
|
62
66
|
@message_keys ||= %w[message]
|
63
67
|
@slack = Fluent::SlackClient::WebApi.new
|
68
|
+
else
|
69
|
+
raise Fluent::ConfigError.new("Either of `webhook_url` or `token` is required")
|
64
70
|
end
|
65
71
|
@slack.log = log
|
66
72
|
@slack.debug_dev = log.out if log.level <= Fluent::Log::LEVEL_TRACE
|
@@ -84,6 +90,8 @@ module Fluent
|
|
84
90
|
raise Fluent::ConfigError, "string specifier '%s' for `channel` and `channel_keys` specification mismatch"
|
85
91
|
end
|
86
92
|
end
|
93
|
+
|
94
|
+
@post_message_opts = @auto_channels_create ? {auto_channels_create: true} : {}
|
87
95
|
end
|
88
96
|
|
89
97
|
def format(tag, time, record)
|
@@ -93,7 +101,7 @@ module Fluent
|
|
93
101
|
def write(chunk)
|
94
102
|
begin
|
95
103
|
payloads = build_payloads(chunk)
|
96
|
-
payloads.each {|payload| @slack.post_message(payload) }
|
104
|
+
payloads.each {|payload| @slack.post_message(payload, @post_message_opts) }
|
97
105
|
rescue Net::OpenTimeout, Net::ReadTimeout => e
|
98
106
|
log.warn "out_slack:", :error => e.to_s, :error_class => e.class.to_s
|
99
107
|
raise e # let Fluentd retry
|
@@ -11,22 +11,23 @@ module Fluent
|
|
11
11
|
config_set_default :include_time_key, true
|
12
12
|
config_set_default :include_tag_key, true
|
13
13
|
|
14
|
-
config_param :webhook_url,
|
15
|
-
config_param :token,
|
16
|
-
config_param :username,
|
17
|
-
config_param :color,
|
18
|
-
config_param :icon_emoji,
|
19
|
-
|
20
|
-
|
21
|
-
config_param :
|
14
|
+
config_param :webhook_url, :string, default: nil # incoming webhook
|
15
|
+
config_param :token, :string, default: nil # api token
|
16
|
+
config_param :username, :string, default: 'fluentd'
|
17
|
+
config_param :color, :string, default: 'good'
|
18
|
+
config_param :icon_emoji, :string, default: ':question:'
|
19
|
+
config_param :auto_channels_create, :bool, default: false
|
20
|
+
|
21
|
+
config_param :channel, :string
|
22
|
+
config_param :channel_keys, default: nil do |val|
|
22
23
|
val.split(',')
|
23
24
|
end
|
24
|
-
config_param :title,
|
25
|
-
config_param :title_keys,
|
25
|
+
config_param :title, :string, default: nil
|
26
|
+
config_param :title_keys, default: nil do |val|
|
26
27
|
val.split(',')
|
27
28
|
end
|
28
|
-
config_param :message,
|
29
|
-
config_param :message_keys,
|
29
|
+
config_param :message, :string, default: nil
|
30
|
+
config_param :message_keys, default: nil do |val|
|
30
31
|
val.split(',')
|
31
32
|
end
|
32
33
|
|
@@ -48,19 +49,24 @@ module Fluent
|
|
48
49
|
@channel = '#' + @channel unless @channel.start_with?('#')
|
49
50
|
|
50
51
|
if @webhook_url
|
52
|
+
if @webhook_url.empty?
|
53
|
+
raise Fluent::ConfigError.new("`webhook_url` is an empty string")
|
54
|
+
end
|
51
55
|
# following default values are for old version compatibility
|
52
56
|
@title ||= '%s'
|
53
57
|
@title_keys ||= %w[tag]
|
54
58
|
@message ||= '[%s] %s'
|
55
59
|
@message_keys ||= %w[time message]
|
56
60
|
@slack = Fluent::SlackClient::IncomingWebhook.new(@webhook_url)
|
57
|
-
|
58
|
-
|
59
|
-
raise Fluent::ConfigError.new("`token` is
|
61
|
+
elsif @token
|
62
|
+
if @token.empty?
|
63
|
+
raise Fluent::ConfigError.new("`token` is an empty string")
|
60
64
|
end
|
61
65
|
@message ||= '%s'
|
62
66
|
@message_keys ||= %w[message]
|
63
67
|
@slack = Fluent::SlackClient::WebApi.new
|
68
|
+
else
|
69
|
+
raise Fluent::ConfigError.new("Either of `webhook_url` or `token` is required")
|
64
70
|
end
|
65
71
|
@slack.log = log
|
66
72
|
@slack.debug_dev = log.out if log.level <= Fluent::Log::LEVEL_TRACE
|
@@ -84,6 +90,8 @@ module Fluent
|
|
84
90
|
raise Fluent::ConfigError, "string specifier '%s' for `channel` and `channel_keys` specification mismatch"
|
85
91
|
end
|
86
92
|
end
|
93
|
+
|
94
|
+
@post_message_opts = @auto_channels_create ? {auto_channels_create: true} : {}
|
87
95
|
end
|
88
96
|
|
89
97
|
def format(tag, time, record)
|
@@ -93,7 +101,7 @@ module Fluent
|
|
93
101
|
def write(chunk)
|
94
102
|
begin
|
95
103
|
payloads = build_payloads(chunk)
|
96
|
-
payloads.each {|payload| @slack.post_message(payload) }
|
104
|
+
payloads.each {|payload| @slack.post_message(payload, @post_message_opts) }
|
97
105
|
rescue Net::OpenTimeout, Net::ReadTimeout => e
|
98
106
|
log.warn "out_slack:", :error => e.to_s, :error_class => e.class.to_s
|
99
107
|
raise e # let Fluentd retry
|
@@ -1,51 +1,19 @@
|
|
1
1
|
require 'uri'
|
2
2
|
require 'net/http'
|
3
|
+
require 'logger'
|
4
|
+
require_relative 'slack_client/error'
|
3
5
|
|
4
6
|
module Fluent
|
5
7
|
module SlackClient
|
6
|
-
|
7
|
-
|
8
|
-
# This slack client only supports posting message
|
8
|
+
# The base framework of slack client
|
9
9
|
class Base
|
10
10
|
attr_accessor :log, :debug_dev
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
def initialize(endpoint = nil)
|
15
|
-
# Configure Incoming Webhook endpoint instead of chat.postMessage API
|
16
|
-
@endpoint = URI.parse(endpoint) if endpoint
|
12
|
+
def initialize
|
13
|
+
@log = Logger.new('/dev/null')
|
17
14
|
end
|
18
15
|
|
19
|
-
def endpoint
|
20
|
-
@endpoint ||= URI.parse(DEFAULT_ENDPOINT)
|
21
|
-
end
|
22
|
-
|
23
|
-
# Sends a message to a channel.
|
24
|
-
#
|
25
|
-
# @option params [channel] :channel
|
26
|
-
# Channel to send message to. Can be a public channel, private group or IM channel. Can be an encoded ID, or a name.
|
27
|
-
# @option params [Object] :text
|
28
|
-
# Text of the message to send. See below for an explanation of formatting.
|
29
|
-
# @option params [Object] :username
|
30
|
-
# Name of bot.
|
31
|
-
# @option params [Object] :parse
|
32
|
-
# Change how messages are treated. See below.
|
33
|
-
# @option params [Object] :link_names
|
34
|
-
# Find and link channel names and usernames.
|
35
|
-
# @option params [Object] :attachments
|
36
|
-
# Structured message attachments.
|
37
|
-
# @option params [Object] :unfurl_links
|
38
|
-
# Pass true to enable unfurling of primarily text-based content.
|
39
|
-
# @option params [Object] :unfurl_media
|
40
|
-
# Pass false to disable unfurling of media content.
|
41
|
-
# @option params [Object] :icon_url
|
42
|
-
# URL to an image to use as the icon for this message
|
43
|
-
# @option params [Object] :icon_emoji
|
44
|
-
# emoji to use as the icon for this message. Overrides `icon_url`.
|
45
|
-
# @see https://api.slack.com/methods/chat.postMessage
|
46
|
-
# @see https://github.com/slackhq/slack-api-docs/blob/master/methods/chat.postMessage.md
|
47
|
-
# @see https://github.com/slackhq/slack-api-docs/blob/master/methods/chat.postMessage.json
|
48
|
-
def post_message(params = {})
|
16
|
+
def post(endpoint, params)
|
49
17
|
http = Net::HTTP.new(endpoint.host, endpoint.port)
|
50
18
|
http.use_ssl = (endpoint.scheme == 'https')
|
51
19
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
@@ -57,36 +25,100 @@ module Fluent
|
|
57
25
|
req['User-Agent'] = 'fluent-plugin-slack'
|
58
26
|
req.body = encode_body(params)
|
59
27
|
|
60
|
-
log.info { "out_slack: post #{params.dup.tap {|p| p[:token] = '[FILTERED]' if p[:token] }}" } if log
|
61
28
|
res = http.request(req)
|
62
|
-
response_check(res)
|
29
|
+
response_check(res, params)
|
63
30
|
end
|
64
31
|
|
32
|
+
private
|
33
|
+
|
65
34
|
def encode_body(params)
|
66
35
|
raise NotImplementedError
|
67
36
|
end
|
68
37
|
|
69
|
-
def response_check(res)
|
38
|
+
def response_check(res, params)
|
70
39
|
if res.code != "200"
|
71
|
-
raise Error
|
40
|
+
raise Error.new(res, params)
|
72
41
|
end
|
73
42
|
end
|
74
43
|
end
|
75
44
|
|
45
|
+
# Slack client for Incoming Webhook
|
76
46
|
class IncomingWebhook < Base
|
47
|
+
attr_accessor :endpoint
|
48
|
+
|
49
|
+
# @param [String] endpoint Configure Incoming Webhook endpoint
|
50
|
+
def initialize(endpoint)
|
51
|
+
super()
|
52
|
+
@endpoint = URI.parse(endpoint)
|
53
|
+
end
|
54
|
+
|
55
|
+
def post_message(params = {}, opts = {})
|
56
|
+
log.info { "out_slack: post_message #{params}" }
|
57
|
+
post(endpoint, params)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
77
62
|
def encode_body(params = {})
|
78
63
|
params.to_json
|
79
64
|
end
|
80
65
|
|
81
|
-
def response_check(res)
|
66
|
+
def response_check(res, params)
|
82
67
|
super
|
83
68
|
unless res.body == 'ok'
|
84
|
-
raise Error
|
69
|
+
raise Error.new(res, params)
|
85
70
|
end
|
86
71
|
end
|
87
72
|
end
|
88
73
|
|
74
|
+
# Slack client for Web API
|
89
75
|
class WebApi < Base
|
76
|
+
DEFAULT_ENDPOINT = "https://slack.com/api/".freeze
|
77
|
+
|
78
|
+
def post_message_endpoint
|
79
|
+
@post_message_endpoint ||= URI.join(DEFAULT_ENDPOINT, "chat.postMessage")
|
80
|
+
end
|
81
|
+
|
82
|
+
def channels_create_endpoint
|
83
|
+
@channels_create_endpoint ||= URI.join(DEFAULT_ENDPOINT, "channels.create")
|
84
|
+
end
|
85
|
+
|
86
|
+
# Sends a message to a channel.
|
87
|
+
#
|
88
|
+
# @see https://api.slack.com/methods/chat.postMessage
|
89
|
+
# @see https://github.com/slackhq/slack-api-docs/blob/master/methods/chat.postMessage.md
|
90
|
+
# @see https://github.com/slackhq/slack-api-docs/blob/master/methods/chat.postMessage.json
|
91
|
+
def post_message(params = {}, opts = {})
|
92
|
+
retries = 1
|
93
|
+
begin
|
94
|
+
log.info { "out_slack: post_message #{params.dup.tap {|p| p[:token] = '[FILTERED]' if p[:token] }}" }
|
95
|
+
post(post_message_endpoint, params)
|
96
|
+
rescue ChannelNotFoundError => e
|
97
|
+
if opts[:auto_channels_create]
|
98
|
+
log.warn "out_slack: channel \"#{params[:channel]}\" is not found. try to create the channel, and then retry to post the message."
|
99
|
+
channels_create({name: params[:channel], token: params[:token]})
|
100
|
+
retry if (retries -= 1) >= 0 # one time retry
|
101
|
+
else
|
102
|
+
raise e
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Creates a channel.
|
108
|
+
#
|
109
|
+
# NOTE: Bot user can not create a channel. Token must be issued by Normal User Account
|
110
|
+
# @see https://api.slack.com/bot-users
|
111
|
+
#
|
112
|
+
# @see https://api.slack.com/methods/channels.create
|
113
|
+
# @see https://github.com/slackhq/slack-api-docs/blob/master/methods/channels.create.md
|
114
|
+
# @see https://github.com/slackhq/slack-api-docs/blob/master/methods/channels.create.json
|
115
|
+
def channels_create(params = {}, opts = {})
|
116
|
+
log.info { "out_slack: channels_create #{params.dup.tap {|p| p[:token] = '[FILTERED]' if p[:token] }}" }
|
117
|
+
post(channels_create_endpoint, params)
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
|
90
122
|
def encode_body(params = {})
|
91
123
|
body = params.dup
|
92
124
|
if params[:attachments]
|
@@ -95,11 +127,17 @@ module Fluent
|
|
95
127
|
URI.encode_www_form(body)
|
96
128
|
end
|
97
129
|
|
98
|
-
def response_check(res)
|
130
|
+
def response_check(res, params)
|
99
131
|
super
|
100
|
-
|
101
|
-
|
102
|
-
|
132
|
+
res_params = JSON.parse(res.body)
|
133
|
+
return if res_params['ok']
|
134
|
+
case res_params['error']
|
135
|
+
when 'channel_not_found'
|
136
|
+
raise ChannelNotFoundError.new(res, params)
|
137
|
+
when 'name_taken'
|
138
|
+
raise NameTakenError.new(res, params)
|
139
|
+
else
|
140
|
+
raise Error.new(res, params)
|
103
141
|
end
|
104
142
|
end
|
105
143
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module Fluent
|
4
|
+
module SlackClient
|
5
|
+
class Error < StandardError
|
6
|
+
attr_reader :res, :req_params
|
7
|
+
|
8
|
+
def initialize(res, req_params = {})
|
9
|
+
@res = res
|
10
|
+
@req_params = req_params.dup
|
11
|
+
end
|
12
|
+
|
13
|
+
def message
|
14
|
+
@req_params[:token] = '[FILTERED]' if @req_params[:token]
|
15
|
+
"res.code:#{@res.code}, res.body:#{@res.body}, req_params:#{@req_params}"
|
16
|
+
end
|
17
|
+
|
18
|
+
alias :to_s :message
|
19
|
+
end
|
20
|
+
|
21
|
+
class ChannelNotFoundError < Error; end
|
22
|
+
class NameTakenError < Error; end
|
23
|
+
end
|
24
|
+
end
|
data/test.sh
ADDED
@@ -83,6 +83,21 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
83
83
|
assert_raise(Fluent::ConfigError) do
|
84
84
|
create_driver(CONFIG + %[channel %s %s\nchannel_keys foo])
|
85
85
|
end
|
86
|
+
|
87
|
+
# Either of webhook_url or token is required
|
88
|
+
assert_raise(Fluent::ConfigError) do
|
89
|
+
create_driver(%[channel foo])
|
90
|
+
end
|
91
|
+
|
92
|
+
# webhook_url is an empty string
|
93
|
+
assert_raise(Fluent::ConfigError) do
|
94
|
+
create_driver(%[channel foo\nwebhook_url])
|
95
|
+
end
|
96
|
+
|
97
|
+
# token is an empty string
|
98
|
+
assert_raise(Fluent::ConfigError) do
|
99
|
+
create_driver(%[channel foo\ntoken])
|
100
|
+
end
|
86
101
|
end
|
87
102
|
|
88
103
|
def test_timezone_configure
|
@@ -129,7 +144,7 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
129
144
|
])
|
130
145
|
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
131
146
|
d.tag = 'test'
|
132
|
-
mock(d.instance.slack).post_message(
|
147
|
+
mock(d.instance.slack).post_message({
|
133
148
|
channel: '#channel',
|
134
149
|
username: 'fluentd',
|
135
150
|
icon_emoji: ':question:',
|
@@ -141,7 +156,7 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
141
156
|
value: "[07:00:00] sowawa1\n[07:00:00] sowawa2\n",
|
142
157
|
}],
|
143
158
|
}]
|
144
|
-
)
|
159
|
+
}, {})
|
145
160
|
with_timezone('Asia/Tokyo') do
|
146
161
|
d.emit({message: 'sowawa1'}, time)
|
147
162
|
d.emit({message: 'sowawa2'}, time)
|
@@ -156,7 +171,7 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
156
171
|
])
|
157
172
|
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
158
173
|
d.tag = 'test'
|
159
|
-
mock(d.instance.slack).post_message(
|
174
|
+
mock(d.instance.slack).post_message({
|
160
175
|
token: 'XX-XX-XX',
|
161
176
|
channel: '#channel',
|
162
177
|
username: 'fluentd',
|
@@ -166,7 +181,7 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
166
181
|
fallback: "sowawa1\nsowawa2\n",
|
167
182
|
text: "sowawa1\nsowawa2\n",
|
168
183
|
}]
|
169
|
-
)
|
184
|
+
}, {})
|
170
185
|
with_timezone('Asia/Tokyo') do
|
171
186
|
d.emit({message: 'sowawa1'}, time)
|
172
187
|
d.emit({message: 'sowawa2'}, time)
|
@@ -179,7 +194,7 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
179
194
|
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
180
195
|
d.tag = 'test'
|
181
196
|
# attachments field should be changed to show the title
|
182
|
-
mock(d.instance.slack).post_message(
|
197
|
+
mock(d.instance.slack).post_message({
|
183
198
|
token: 'XXX-XXX-XXX',
|
184
199
|
channel: '#channel',
|
185
200
|
username: 'fluentd',
|
@@ -194,7 +209,7 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
194
209
|
}
|
195
210
|
]
|
196
211
|
}]
|
197
|
-
)
|
212
|
+
}, {})
|
198
213
|
with_timezone('Asia/Tokyo') do
|
199
214
|
d.emit({message: 'sowawa1'}, time)
|
200
215
|
d.emit({message: 'sowawa2'}, time)
|
@@ -206,7 +221,7 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
206
221
|
d = create_driver(CONFIG + %[message %s %s\nmessage_keys tag,message])
|
207
222
|
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
208
223
|
d.tag = 'test'
|
209
|
-
mock(d.instance.slack).post_message(
|
224
|
+
mock(d.instance.slack).post_message({
|
210
225
|
token: 'XXX-XXX-XXX',
|
211
226
|
channel: '#channel',
|
212
227
|
username: 'fluentd',
|
@@ -216,7 +231,7 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
216
231
|
fallback: "test sowawa1\ntest sowawa2\n",
|
217
232
|
text: "test sowawa1\ntest sowawa2\n",
|
218
233
|
}]
|
219
|
-
)
|
234
|
+
}, {})
|
220
235
|
with_timezone('Asia/Tokyo') do
|
221
236
|
d.emit({message: 'sowawa1'}, time)
|
222
237
|
d.emit({message: 'sowawa2'}, time)
|
@@ -228,7 +243,7 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
228
243
|
d = create_driver(CONFIG + %[channel %s\nchannel_keys channel])
|
229
244
|
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
230
245
|
d.tag = 'test'
|
231
|
-
mock(d.instance.slack).post_message(
|
246
|
+
mock(d.instance.slack).post_message({
|
232
247
|
token: 'XXX-XXX-XXX',
|
233
248
|
channel: '#channel1',
|
234
249
|
username: 'fluentd',
|
@@ -238,8 +253,8 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
238
253
|
fallback: "sowawa1\n",
|
239
254
|
text: "sowawa1\n",
|
240
255
|
}]
|
241
|
-
)
|
242
|
-
mock(d.instance.slack).post_message(
|
256
|
+
}, {})
|
257
|
+
mock(d.instance.slack).post_message({
|
243
258
|
token: 'XXX-XXX-XXX',
|
244
259
|
channel: '#channel2',
|
245
260
|
username: 'fluentd',
|
@@ -249,7 +264,7 @@ class SlackOutputTest < Test::Unit::TestCase
|
|
249
264
|
fallback: "sowawa2\n",
|
250
265
|
text: "sowawa2\n",
|
251
266
|
}]
|
252
|
-
)
|
267
|
+
}, {})
|
253
268
|
with_timezone('Asia/Tokyo') do
|
254
269
|
d.emit({message: 'sowawa1', channel: 'channel1'}, time)
|
255
270
|
d.emit({message: 'sowawa2', channel: 'channel2'}, time)
|
@@ -23,7 +23,7 @@ if ENV['WEBHOOK_URL'] and ENV['TOKEN']
|
|
23
23
|
client == @api ? {token: ENV['TOKEN']} : {}
|
24
24
|
end
|
25
25
|
|
26
|
-
def
|
26
|
+
def test_post_message_text
|
27
27
|
[@incoming_webhook, @api].each do |slack|
|
28
28
|
assert_nothing_raised do
|
29
29
|
slack.post_message(
|
@@ -42,7 +42,7 @@ if ENV['WEBHOOK_URL'] and ENV['TOKEN']
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
-
def
|
45
|
+
def test_post_message_fields
|
46
46
|
[@incoming_webhook, @api].each do |slack|
|
47
47
|
assert_nothing_raised do
|
48
48
|
slack.post_message(
|
@@ -69,5 +69,40 @@ if ENV['WEBHOOK_URL'] and ENV['TOKEN']
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
end
|
72
|
+
|
73
|
+
# Hmm, I need to delete channels to test repeatedly,
|
74
|
+
# but slack does not provide channels.delete API
|
75
|
+
def test_channels_create
|
76
|
+
begin
|
77
|
+
@api.channels_create(
|
78
|
+
{
|
79
|
+
name: '#foo',
|
80
|
+
}.merge(token(@api))
|
81
|
+
)
|
82
|
+
rescue Fluent::SlackClient::NameTakenError
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Hmm, I need to delete channels to test repeatedly,
|
87
|
+
# but slack does not provide channels.delete API
|
88
|
+
def test_auto_channels_create
|
89
|
+
assert_nothing_raised do
|
90
|
+
@api.post_message(
|
91
|
+
{
|
92
|
+
channel: '#bar',
|
93
|
+
username: 'fluentd',
|
94
|
+
icon_emoji: ':question:',
|
95
|
+
attachments: [{
|
96
|
+
color: 'good',
|
97
|
+
fallback: "bar\n",
|
98
|
+
text: "bar\n",
|
99
|
+
}]
|
100
|
+
}.merge(token(@api)),
|
101
|
+
{
|
102
|
+
auto_channels_create: true,
|
103
|
+
}
|
104
|
+
)
|
105
|
+
end
|
106
|
+
end
|
72
107
|
end
|
73
108
|
end
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-slack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keisuke SOGAWA
|
8
|
+
- Naotoshi Seo
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
12
|
+
date: 2015-03-27 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: fluentd
|
@@ -123,21 +124,27 @@ dependencies:
|
|
123
124
|
- !ruby/object:Gem::Version
|
124
125
|
version: '0'
|
125
126
|
description: fluent Slack plugin
|
126
|
-
email:
|
127
|
+
email:
|
128
|
+
- keisuke.sogawa@gmail.com
|
129
|
+
- sonots@gmail.com
|
127
130
|
executables: []
|
128
131
|
extensions: []
|
129
132
|
extra_rdoc_files: []
|
130
133
|
files:
|
131
134
|
- ".gitignore"
|
132
|
-
-
|
135
|
+
- ".travis.yml"
|
136
|
+
- CHANGELOG.md
|
133
137
|
- Gemfile
|
134
138
|
- README.md
|
135
139
|
- Rakefile
|
136
140
|
- VERSION
|
141
|
+
- example.conf
|
137
142
|
- fluent-plugin-slack.gemspec
|
138
143
|
- lib/fluent/plugin/out_buffered_slack.rb
|
139
144
|
- lib/fluent/plugin/out_slack.rb
|
140
145
|
- lib/fluent/plugin/slack_client.rb
|
146
|
+
- lib/fluent/plugin/slack_client/error.rb
|
147
|
+
- test.sh
|
141
148
|
- test/plugin/test_out_slack.rb
|
142
149
|
- test/plugin/test_slack_client.rb
|
143
150
|
- test/test_helper.rb
|
data/AUTHORS
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
Keisuke SOGAWA <keisuke.sogawa _at_ gmail.com>
|