fluent-plugin-google-chat 0.0.1
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 +7 -0
- data/.gitignore +10 -0
- data/.travis.yml +11 -0
- data/CHANGELOG.md +95 -0
- data/Gemfile +3 -0
- data/Gemfile.fluentd.0.12 +4 -0
- data/README.md +61 -0
- data/Rakefile +16 -0
- data/VERSION +1 -0
- data/docker.sh +1 -0
- data/example.conf +12 -0
- data/fluent-plugin-google-chat.gemspec +29 -0
- data/lib/fluent/plugin/google_chat_client.rb +92 -0
- data/lib/fluent/plugin/google_chat_client/error.rb +24 -0
- data/lib/fluent/plugin/out_buffered_google_chat.rb +1 -0
- data/lib/fluent/plugin/out_google_chat.rb +171 -0
- data/test.sh +2 -0
- data/test/plugin/test_google_chat_client.rb +130 -0
- data/test/plugin/test_out_google_chat.rb +223 -0
- data/test/test_helper.rb +32 -0
- data/todelete.rb +13 -0
- metadata +206 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a06d61a542fae23221eb956df8a0f23157c1a94a6475135d4e844c453a238501
|
4
|
+
data.tar.gz: dc7104521deeb08323c4de39c1c0dea7a4e5cea52ac482f3e63f9565941f20d5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 299a8bf7403aba535cbf8d2d609b4ef9252b3b88dcbaacb6ab426e90ebe159bdd954a3ac3380afadcd9fd2f53fc2dd83abf7b48ee2cae5e0b1590f183824ff99
|
7
|
+
data.tar.gz: ed60576f6b3638038062aaf8f6d9e5b4ed73edf448ee7ae4b6f849bce9b6f8f4e58d54d580994045b27df594f44dd43dcfebfddbec5d9e6b22cf4a8633c4c4aa
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
## 0.6.7 (2017/05/23)
|
2
|
+
|
3
|
+
Enhancements:
|
4
|
+
|
5
|
+
* Allow channel @username (DM)
|
6
|
+
|
7
|
+
## 0.6.6 (2017/05/23)
|
8
|
+
|
9
|
+
Enhancements:
|
10
|
+
|
11
|
+
* Make channel config optional on webhook because webhook has its defaul channel setting (thanks to @hirakiuc)
|
12
|
+
|
13
|
+
## 0.6.5 (2017/05/20)
|
14
|
+
|
15
|
+
Enhancements:
|
16
|
+
|
17
|
+
* Avoid Encoding::UndefinedConversionError from ASCII-8BIT to UTF-8 on to_json by doing String#scrub! (thanks @yoheimuta)
|
18
|
+
|
19
|
+
## 0.6.4 (2016/07/07)
|
20
|
+
|
21
|
+
Enhancements:
|
22
|
+
|
23
|
+
* Add `as_user` option (thanks @yacchin1205)
|
24
|
+
|
25
|
+
## 0.6.3 (2016/05/11)
|
26
|
+
|
27
|
+
Enhancements:
|
28
|
+
|
29
|
+
* Add `verbose_fallback` option to show fallback (popup) verbosely (thanks @eisuke)
|
30
|
+
|
31
|
+
## 0.6.2 (2015/12/17)
|
32
|
+
|
33
|
+
Fixes:
|
34
|
+
|
35
|
+
* escape special characters in message (thanks @fujiwara)
|
36
|
+
|
37
|
+
## 0.6.1 (2015/05/17)
|
38
|
+
|
39
|
+
Fixes:
|
40
|
+
|
41
|
+
* Support ruby 1.9.3
|
42
|
+
|
43
|
+
## 0.6.0 (2015/04/02)
|
44
|
+
|
45
|
+
This version has impcompatibility with previous versions in default option values
|
46
|
+
|
47
|
+
Enhancements:
|
48
|
+
|
49
|
+
* Support `link_names` and `parse` option. `link_names` option is `true` as default
|
50
|
+
|
51
|
+
Changes:
|
52
|
+
|
53
|
+
* the default payload of Incoming Webhook was changed
|
54
|
+
* `color` is `nil` as default
|
55
|
+
* `icon_emoji` is `nil` as default
|
56
|
+
* `username` is `nil` as default
|
57
|
+
* `mrkdwn` is `true` as default
|
58
|
+
|
59
|
+
## 0.5.5 (2015/04/01)
|
60
|
+
|
61
|
+
Enhancements:
|
62
|
+
|
63
|
+
* Support Slackbot Remote Control API
|
64
|
+
|
65
|
+
## 0.5.4 (2015/03/31)
|
66
|
+
|
67
|
+
Enhancements:
|
68
|
+
|
69
|
+
* Support `mrkdwn` option
|
70
|
+
|
71
|
+
## 0.5.3 (2015/03/29)
|
72
|
+
|
73
|
+
Enhancements:
|
74
|
+
|
75
|
+
* Support `https_proxy` option
|
76
|
+
|
77
|
+
## 0.5.2 (2015/03/29)
|
78
|
+
|
79
|
+
Enhancements:
|
80
|
+
|
81
|
+
* Support `icon_url` option (thanks to @jwyjoy)
|
82
|
+
|
83
|
+
## 0.5.1 (2015/03/27)
|
84
|
+
|
85
|
+
Enhancements:
|
86
|
+
|
87
|
+
* Support `auto_channels_create` option to automatically create channels.
|
88
|
+
|
89
|
+
## 0.5.0 (2015/03/22)
|
90
|
+
|
91
|
+
Enhancements:
|
92
|
+
|
93
|
+
* Support `message` and `message_keys` options
|
94
|
+
* Support `title` and `title_keys` options
|
95
|
+
* Support `channel_keys` options to dynamically change channels
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# fluent-plugin-google-chat [](https://travis-ci.org/treasuryspring/fluent-plugin-google-chat)
|
2
|
+
|
3
|
+
This plugin is largely inspired by [fluent-plugin-slack](https://github.com/sowawa/fluent-plugin-slack).
|
4
|
+
|
5
|
+
# Installation
|
6
|
+
|
7
|
+
```
|
8
|
+
$ fluent-gem install fluent-plugin-google-chat
|
9
|
+
```
|
10
|
+
|
11
|
+
# Usage (Web API a.k.a. Bots)
|
12
|
+
|
13
|
+
```apache
|
14
|
+
<match google_chat>
|
15
|
+
@type google_chat
|
16
|
+
keyfile /tmp/mykeyfile.json
|
17
|
+
space AAABBBcdefG
|
18
|
+
flush_interval 60s
|
19
|
+
</match>
|
20
|
+
```
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
fluent_logger.post('google_chat', {
|
24
|
+
:message => 'Hello<br>World!'
|
25
|
+
})
|
26
|
+
```
|
27
|
+
|
28
|
+
### Parameter
|
29
|
+
|
30
|
+
|parameter|description|default|
|
31
|
+
|---|---|---|
|
32
|
+
|keyfile|Private key file generated on Google Cloud Platform. See https://developers.google.com/hangouts/chat/how-tos/bots-publish#enabling_the_hangouts_chat_api||
|
33
|
+
|space|Room name to send messages. Can be found in the URL of the chat room.||
|
34
|
+
|space_keys|keys used to format space. %s will be replaced with value specified by space_keys if this option is used|nil|
|
35
|
+
|message|message format. %s will be replaced with value specified by message_keys|%s|
|
36
|
+
|message_keys|keys used to format messages|message|
|
37
|
+
|https_proxy|https proxy url such as `https://proxy.foo.bar:443`|nil|
|
38
|
+
|verbose_fallback|If this option is set to be `true`, messages are included to the fallback attribute|false|
|
39
|
+
|
40
|
+
`fluent-plugin-google-chat` uses `SetTimeKeyMixin` and `SetTagKeyMixin`, so you can also use:
|
41
|
+
|
42
|
+
|parameter|description|default|
|
43
|
+
|---|---|---|
|
44
|
+
|timezone|timezone such as `Asia/Tokyo`||
|
45
|
+
|localtime|use localtime as timezone|true|
|
46
|
+
|utc|use utc as timezone||
|
47
|
+
|time_key|key name for time used in xxx_keys|time|
|
48
|
+
|time_format|time format. This will be formatted with Time#strftime.|%H:%M:%S|
|
49
|
+
|tag_key|key name for tag used in xxx_keys|tag|
|
50
|
+
|
51
|
+
`fluent-plugin-google-chat` is a kind of BufferedOutput plugin, so you can also use [Buffer Parameters](http://docs.fluentd.org/articles/out_exec#buffer-parameters).
|
52
|
+
|
53
|
+
## ChangeLog
|
54
|
+
|
55
|
+
See [CHANGELOG.md](CHANGELOG.md) for details.
|
56
|
+
|
57
|
+
# Copyright
|
58
|
+
|
59
|
+
* Copyright:: Copyright (c) 2020 - TreasurySpring
|
60
|
+
* License:: Apache License, Version 2.0
|
61
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
|
4
|
+
require 'rake/testtask'
|
5
|
+
Rake::TestTask.new(:test) do |test|
|
6
|
+
test.libs << 'lib' << 'test'
|
7
|
+
test.pattern = 'test/**/test_*.rb'
|
8
|
+
test.verbose = true
|
9
|
+
end
|
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
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/docker.sh
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
docker run --rm -ti
|
data/example.conf
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = "fluent-plugin-google-chat"
|
6
|
+
gem.description = "fluent Google Chat plugin"
|
7
|
+
gem.homepage = "https://github.com/treasuryspring/fluent-plugin-google-chat"
|
8
|
+
gem.license = "Apache-2.0"
|
9
|
+
gem.summary = gem.description
|
10
|
+
gem.version = File.read("VERSION").strip
|
11
|
+
gem.authors = ["Lionel Gabaude"]
|
12
|
+
gem.email = ["tech@treasuryspring.com"]
|
13
|
+
gem.files = `git ls-files`.split("\n")
|
14
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
|
+
gem.require_paths = ['lib']
|
17
|
+
|
18
|
+
gem.add_dependency "fluentd", ">= 0.12.0"
|
19
|
+
gem.add_dependency "googleauth"
|
20
|
+
gem.add_dependency "google-api-client", "~> 0.34"
|
21
|
+
|
22
|
+
gem.add_development_dependency "rake", ">= 10.1.1"
|
23
|
+
gem.add_development_dependency "rr", ">= 1.0.0"
|
24
|
+
gem.add_development_dependency "pry"
|
25
|
+
gem.add_development_dependency "pry-nav"
|
26
|
+
gem.add_development_dependency "test-unit", "~> 3.0.2"
|
27
|
+
gem.add_development_dependency "test-unit-rr", "~> 1.0.3"
|
28
|
+
gem.add_development_dependency "dotenv"
|
29
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
require 'net/https'
|
4
|
+
require 'logger'
|
5
|
+
require 'googleauth'
|
6
|
+
require 'google/apis/chat_v1'
|
7
|
+
require_relative 'google_chat_client/error'
|
8
|
+
|
9
|
+
Chat = Google::Apis::ChatV1
|
10
|
+
|
11
|
+
module Fluent
|
12
|
+
module GoogleChatClient
|
13
|
+
# The base framework of google_chat client
|
14
|
+
class Base
|
15
|
+
SCOPE = 'https://www.googleapis.com/auth/chat.bot'.freeze
|
16
|
+
|
17
|
+
attr_accessor :log, :debug_dev
|
18
|
+
attr_reader :keyfile, :https_proxy
|
19
|
+
|
20
|
+
# @param [String] endpoint
|
21
|
+
#
|
22
|
+
# (Incoming Webhook) required
|
23
|
+
# https://hooks.slack.com/services/XXX/XXX/XXX
|
24
|
+
#
|
25
|
+
# (Slackbot) required
|
26
|
+
# https://xxxx.slack.com/services/hooks/slackbot?token=XXXXX
|
27
|
+
#
|
28
|
+
# (Web API) optional and default to be
|
29
|
+
# https://slack.com/api/
|
30
|
+
#
|
31
|
+
# @param [String] https_proxy (optional)
|
32
|
+
#
|
33
|
+
# https://proxy.foo.bar:port
|
34
|
+
#
|
35
|
+
def initialize(keyfile = nil, https_proxy = nil)
|
36
|
+
self.keyfile = keyfile if keyfile
|
37
|
+
self.https_proxy = https_proxy if https_proxy
|
38
|
+
@log = Logger.new('/dev/null')
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Ensure valid credentials, either by restoring from the saved credentials
|
43
|
+
# files or intitiating an OAuth2 authorization. If authorization is required,
|
44
|
+
# the user's default browser will be launched to approve the request.
|
45
|
+
#
|
46
|
+
# @return [Google::Auth::UserRefreshCredentials] OAuth2 credentials
|
47
|
+
def authorize
|
48
|
+
credentials = Google::Auth::ServiceAccountCredentials.make_creds(
|
49
|
+
json_key_io: File.open(self.keyfile),
|
50
|
+
scope: SCOPE
|
51
|
+
)
|
52
|
+
credentials
|
53
|
+
end
|
54
|
+
|
55
|
+
def keyfile=(keyfile)
|
56
|
+
@keyfile = keyfile
|
57
|
+
end
|
58
|
+
|
59
|
+
def https_proxy=(https_proxy)
|
60
|
+
@https_proxy = URI.parse(https_proxy)
|
61
|
+
@proxy_class = Net::HTTP.Proxy(@https_proxy.host, @https_proxy.port)
|
62
|
+
end
|
63
|
+
|
64
|
+
def proxy_class
|
65
|
+
@proxy_class ||= Net::HTTP
|
66
|
+
end
|
67
|
+
|
68
|
+
def post(params)
|
69
|
+
chat = Chat::HangoutsChatService.new
|
70
|
+
chat.authorization = authorize
|
71
|
+
message = Chat::Message.new
|
72
|
+
message.text = params[:text]
|
73
|
+
|
74
|
+
chat.create_space_message(
|
75
|
+
'spaces/%s' % params[:space],
|
76
|
+
message
|
77
|
+
)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# GoogleChat client
|
82
|
+
class WebApi < Base
|
83
|
+
# Sends a message to a space.
|
84
|
+
def post_message(params = {})
|
85
|
+
log.info { "out_google_chat: post_message #{params}" }
|
86
|
+
post(params)
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module Fluent
|
4
|
+
module GoogleChatClient
|
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 SpaceNotFoundError < Error; end
|
22
|
+
class NameTakenError < Error; end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
lib/fluent/plugin/Users/lgabaude/Documents/ts/fluent-plugin-google-chat/lib/fluent/plugin/out_google
|
@@ -0,0 +1,171 @@
|
|
1
|
+
require_relative 'google_chat_client'
|
2
|
+
|
3
|
+
module Fluent
|
4
|
+
class GoogleChatOutput < Fluent::BufferedOutput
|
5
|
+
Fluent::Plugin.register_output('buffered_google_chat', self) # old version compatiblity
|
6
|
+
Fluent::Plugin.register_output('google_chat', self)
|
7
|
+
|
8
|
+
# For fluentd v0.12.16 or earlier
|
9
|
+
class << self
|
10
|
+
unless method_defined?(:desc)
|
11
|
+
def desc(description)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
include SetTimeKeyMixin
|
17
|
+
include SetTagKeyMixin
|
18
|
+
|
19
|
+
config_set_default :include_time_key, true
|
20
|
+
config_set_default :include_tag_key, true
|
21
|
+
|
22
|
+
desc <<-DESC
|
23
|
+
Incoming Webhook URI (Required for Incoming Webhook mode).
|
24
|
+
See: https://api.slack.com/incoming-webhooks
|
25
|
+
DESC
|
26
|
+
config_param :keyfile, :string, default: nil
|
27
|
+
desc "Private key file."
|
28
|
+
config_param :https_proxy, :string, default: nil
|
29
|
+
|
30
|
+
desc "space to send messages (room id)."
|
31
|
+
config_param :space, :string, default: nil
|
32
|
+
desc <<-DESC
|
33
|
+
Keys used to format space.
|
34
|
+
%s will be replaced with value specified by space_keys if this option is used.
|
35
|
+
DESC
|
36
|
+
config_param :space_keys, default: nil do |val|
|
37
|
+
val.split(',')
|
38
|
+
end
|
39
|
+
desc <<-DESC
|
40
|
+
Message format.
|
41
|
+
%s will be replaced with value specified by message_keys.
|
42
|
+
DESC
|
43
|
+
config_param :message, :string, default: nil
|
44
|
+
desc "Keys used to format messages."
|
45
|
+
config_param :message_keys, default: nil do |val|
|
46
|
+
val.split(',')
|
47
|
+
end
|
48
|
+
|
49
|
+
desc "Include messages to the fallback attributes"
|
50
|
+
config_param :verbose_fallback, :bool, default: false
|
51
|
+
|
52
|
+
# for test
|
53
|
+
attr_reader :google_chat, :time_format, :localtime, :timef, :mrkdwn_in, :post_message_opts
|
54
|
+
|
55
|
+
def initialize
|
56
|
+
super
|
57
|
+
require 'uri'
|
58
|
+
end
|
59
|
+
|
60
|
+
def configure(conf)
|
61
|
+
conf['time_format'] ||= '%H:%M:%S' # old version compatiblity
|
62
|
+
conf['localtime'] ||= true unless conf['utc']
|
63
|
+
|
64
|
+
super
|
65
|
+
|
66
|
+
if @space
|
67
|
+
@space = URI.unescape(@space) # old version compatibility
|
68
|
+
else
|
69
|
+
raise Fluent::ConfigError.new("`space` is required")
|
70
|
+
end
|
71
|
+
|
72
|
+
if @keyfile
|
73
|
+
if @keyfile.empty?
|
74
|
+
raise Fluent::ConfigError.new("`keyfile` is an empty string")
|
75
|
+
end
|
76
|
+
if @keyfile.nil?
|
77
|
+
raise Fluent::ConfigError.new("`keyfile` parameter required for Google Chat")
|
78
|
+
end
|
79
|
+
@google_chat = Fluent::GoogleChatClient::WebApi.new(@keyfile)
|
80
|
+
else
|
81
|
+
raise Fluent::ConfigError.new("`keyfile` is required")
|
82
|
+
end
|
83
|
+
@google_chat.log = log
|
84
|
+
@google_chat.debug_dev = log.out if log.level <= Fluent::Log::LEVEL_TRACE
|
85
|
+
|
86
|
+
if @https_proxy
|
87
|
+
@google_chat.https_proxy = @https_proxy
|
88
|
+
end
|
89
|
+
|
90
|
+
@message ||= '%s'
|
91
|
+
@message_keys ||= %w[message]
|
92
|
+
begin
|
93
|
+
@message % (['1'] * @message_keys.length)
|
94
|
+
rescue ArgumentError
|
95
|
+
raise Fluent::ConfigError, "string specifier '%s' for `message` and `message_keys` specification mismatch"
|
96
|
+
end
|
97
|
+
if @space_keys
|
98
|
+
begin
|
99
|
+
@space % (['1'] * @space_keys.length)
|
100
|
+
rescue ArgumentError
|
101
|
+
raise Fluent::ConfigError, "string specifier '%s' for `space` and `space_keys` specification mismatch"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def format(tag, time, record)
|
107
|
+
[tag, time, record].to_msgpack
|
108
|
+
end
|
109
|
+
|
110
|
+
def write(chunk)
|
111
|
+
begin
|
112
|
+
payloads = build_payloads(chunk)
|
113
|
+
payloads.each {|payload| @google_chat.post_message(payload) }
|
114
|
+
rescue Timeout::Error => e
|
115
|
+
log.warn "out_google_chat:", :error => e.to_s, :error_class => e.class.to_s
|
116
|
+
raise e # let Fluentd retry
|
117
|
+
rescue => e
|
118
|
+
log.error "out_google_chat:", :error => e.to_s, :error_class => e.class.to_s
|
119
|
+
log.warn_backtrace e.backtrace
|
120
|
+
# discard. @todo: add more retriable errors
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
def build_payloads(chunk)
|
127
|
+
build_plain_payloads(chunk)
|
128
|
+
end
|
129
|
+
|
130
|
+
Field = Struct.new("Field", :title, :value)
|
131
|
+
# ruby 1.9.x does not provide #to_h
|
132
|
+
Field.send(:define_method, :to_h) { {title: title, value: value} }
|
133
|
+
|
134
|
+
def build_plain_payloads(chunk)
|
135
|
+
messages = {}
|
136
|
+
chunk.msgpack_each do |tag, time, record|
|
137
|
+
space = build_space(record)
|
138
|
+
messages[space] ||= ''
|
139
|
+
messages[space] << "#{build_message(record)}\n"
|
140
|
+
end
|
141
|
+
messages.map do |space, text|
|
142
|
+
msg = {text: text}
|
143
|
+
msg.merge!(space: space) if space
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def build_message(record)
|
148
|
+
values = fetch_keys(record, @message_keys)
|
149
|
+
@message % values
|
150
|
+
end
|
151
|
+
|
152
|
+
def build_space(record)
|
153
|
+
return nil if @space.nil?
|
154
|
+
return @space unless @space_keys
|
155
|
+
|
156
|
+
values = fetch_keys(record, @space_keys)
|
157
|
+
@space % values
|
158
|
+
end
|
159
|
+
|
160
|
+
def fetch_keys(record, keys)
|
161
|
+
Array(keys).map do |key|
|
162
|
+
begin
|
163
|
+
record.fetch(key).to_s
|
164
|
+
rescue KeyError
|
165
|
+
log.warn "out_google_chat: the specified key '#{key}' not found in record. [#{record}]"
|
166
|
+
''
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
data/test.sh
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
require 'fluent/plugin/google_chat_client'
|
3
|
+
require 'time'
|
4
|
+
require 'dotenv'
|
5
|
+
require 'webrick'
|
6
|
+
require 'webrick/httpproxy'
|
7
|
+
|
8
|
+
# HOW TO RUN
|
9
|
+
#
|
10
|
+
# Create .env file with contents as:
|
11
|
+
#
|
12
|
+
# WEBHOOK_URL=https://hooks.slack.com/services/XXXX/YYYY/ZZZZ
|
13
|
+
# SLACKBOt_URL=https://xxxx.slack.com/services/hooks/slackbot?token=XXXX
|
14
|
+
# SLACK_API_TOKEN=XXXXX
|
15
|
+
#
|
16
|
+
Dotenv.load
|
17
|
+
if ENV['WEBHOOK_URL'] and ENV['SLACKBOT_URL'] and ENV['SLACK_API_TOKEN']
|
18
|
+
class TestProxyServer
|
19
|
+
def initialize
|
20
|
+
@proxy = WEBrick::HTTPProxyServer.new(
|
21
|
+
:BindAddress => '127.0.0.1',
|
22
|
+
:Port => unused_port,
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
def proxy_url
|
27
|
+
"https://127.0.0.1:#{unused_port}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def start
|
31
|
+
@thread = Thread.new do
|
32
|
+
@proxy.start
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def shutdown
|
37
|
+
@proxy.shutdown
|
38
|
+
end
|
39
|
+
|
40
|
+
def unused_port
|
41
|
+
return @unused_port if @unused_port
|
42
|
+
s = TCPServer.open(0)
|
43
|
+
port = s.addr[1]
|
44
|
+
s.close
|
45
|
+
@unused_port = port
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class GoogleChatClientTest < Test::Unit::TestCase
|
50
|
+
class << self
|
51
|
+
attr_reader :proxy
|
52
|
+
|
53
|
+
def startup
|
54
|
+
@proxy = TestProxyServer.new.tap {|proxy| proxy.start }
|
55
|
+
end
|
56
|
+
|
57
|
+
def shutdown
|
58
|
+
@proxy.shutdown
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def setup
|
63
|
+
super
|
64
|
+
@api = Fluent::GoogleChatClient::WebApi.new
|
65
|
+
|
66
|
+
proxy_url = self.class.proxy.proxy_url
|
67
|
+
@api_proxy = Fluent::GoogleChatClient::WebApi.new(nil, proxy_url)
|
68
|
+
end
|
69
|
+
|
70
|
+
def default_payload(client)
|
71
|
+
{
|
72
|
+
space: 'space',
|
73
|
+
keyfile: 'xxxx.json'
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
def valid_utf8_encoded_string
|
78
|
+
"space \xE3\x82\xA4\xE3\x83\xB3\xE3\x82\xB9\xE3\x83\x88\xE3\x83\xBC\xE3\x83\xAB\n"
|
79
|
+
end
|
80
|
+
|
81
|
+
def invalid_ascii8bit_encoded_utf8_string
|
82
|
+
str = "space \xE3\x82\xA4\xE3\x83\xB3\xE3\x82\xB9\xE3\x83\x88\xE3\x83\xBC\xE3\x83\xAB\x81\n"
|
83
|
+
str.force_encoding(Encoding::ASCII_8BIT)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Notification via Highlight Words works with only Slackbot with plain text payload
|
87
|
+
# NOTE: Please add `sowawa1` to Highlight Words
|
88
|
+
def test_post_message_plain_payload
|
89
|
+
[@api].each do |gc|
|
90
|
+
assert_nothing_raised do
|
91
|
+
gc.post_message(default_payload(gc).merge({
|
92
|
+
text: "treasuryspring\n",
|
93
|
+
}))
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_post_via_proxy
|
99
|
+
[@api_proxy].each do |gc|
|
100
|
+
assert_nothing_raised do
|
101
|
+
gc.post_message(default_payload(gc).merge({
|
102
|
+
text: "treasuryspring\n"
|
103
|
+
}))
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# IncomingWebhook posts "space インストール"
|
109
|
+
def test_post_message_utf8_encoded_text
|
110
|
+
[@incoming].each do |gc|
|
111
|
+
assert_nothing_raised do
|
112
|
+
gc.post_message(default_payload(gc).merge({
|
113
|
+
text: valid_utf8_encoded_string,
|
114
|
+
}))
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# IncomingWebhook posts "space インストール?"
|
120
|
+
def test_post_message_ascii8bit_encoded_utf8_text
|
121
|
+
[@incoming].each do |gc|
|
122
|
+
assert_nothing_raised do
|
123
|
+
gc.post_message(default_payload(gc).merge({
|
124
|
+
text: invalid_ascii8bit_encoded_utf8_string,
|
125
|
+
}))
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,223 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
require 'fluent/plugin/out_google_chat'
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
class GoogleChatOutputTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
super
|
9
|
+
Fluent::Test.setup
|
10
|
+
end
|
11
|
+
|
12
|
+
CONFIG = %[
|
13
|
+
space space
|
14
|
+
]
|
15
|
+
|
16
|
+
def default_payload
|
17
|
+
{
|
18
|
+
space: 'space'
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_driver(conf = CONFIG)
|
23
|
+
Fluent::Test::BufferedOutputTestDriver.new(Fluent::GoogleChatOutput).configure(conf)
|
24
|
+
end
|
25
|
+
|
26
|
+
# old version compatibility with v0.4.0"
|
27
|
+
def test_old_config
|
28
|
+
# default check
|
29
|
+
d = create_driver
|
30
|
+
assert_equal true, d.instance.localtime
|
31
|
+
|
32
|
+
assert_nothing_raised do
|
33
|
+
create_driver(CONFIG + %[api_key testtoken])
|
34
|
+
end
|
35
|
+
|
36
|
+
# incoming webhook endpoint was changed. team option should be ignored
|
37
|
+
assert_nothing_raised do
|
38
|
+
create_driver(CONFIG + %[team treasuryspring])
|
39
|
+
end
|
40
|
+
|
41
|
+
# rtm? it was not calling `rtm.start`. rtm option was removed and should be ignored
|
42
|
+
assert_nothing_raised do
|
43
|
+
create_driver(CONFIG + %[rtm true])
|
44
|
+
end
|
45
|
+
|
46
|
+
# channel should be URI.unescape-ed
|
47
|
+
d = create_driver(CONFIG + %[space %23test])
|
48
|
+
assert_equal 'test', d.instance.space
|
49
|
+
|
50
|
+
# timezone should work
|
51
|
+
d = create_driver(CONFIG + %[timezone Asia/Tokyo])
|
52
|
+
assert_equal 'Asia/Tokyo', d.instance.timezone
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_configure
|
56
|
+
d = create_driver(%[
|
57
|
+
space space
|
58
|
+
time_format %Y/%m/%d %H:%M:%S
|
59
|
+
keyfile xxxx.json
|
60
|
+
message %s
|
61
|
+
message_keys message
|
62
|
+
])
|
63
|
+
assert_equal 'space', d.instance.space
|
64
|
+
assert_equal '%Y/%m/%d %H:%M:%S', d.instance.time_format
|
65
|
+
assert_equal 'xxxx.json', d.instance.keyfile
|
66
|
+
assert_equal '%s', d.instance.message
|
67
|
+
assert_equal ['message'], d.instance.message_keys
|
68
|
+
|
69
|
+
# Allow DM
|
70
|
+
d = create_driver(CONFIG + %[space @test])
|
71
|
+
assert_equal '@test', d.instance.space
|
72
|
+
|
73
|
+
assert_raise(Fluent::ConfigError) do
|
74
|
+
create_driver(CONFIG + %[message %s %s\nmessage_keys foo])
|
75
|
+
end
|
76
|
+
|
77
|
+
assert_raise(Fluent::ConfigError) do
|
78
|
+
create_driver(CONFIG + %[space %s %s\nspace_keys foo])
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_google_chat_configure
|
83
|
+
# keyfile is missing
|
84
|
+
assert_raise(Fluent::ConfigError) do
|
85
|
+
create_driver(%[space foo])
|
86
|
+
end
|
87
|
+
|
88
|
+
# keyfile is an empty string
|
89
|
+
assert_raise(Fluent::ConfigError) do
|
90
|
+
create_driver(%[space foo\nkeyfile])
|
91
|
+
end
|
92
|
+
|
93
|
+
# space is missing
|
94
|
+
assert_raise(Fluent::ConfigError) do
|
95
|
+
create_driver(%[keyfile xxxx.json])
|
96
|
+
end
|
97
|
+
|
98
|
+
# space is an empty string
|
99
|
+
assert_raise(Fluent::ConfigError) do
|
100
|
+
create_driver(%[space\nkeyfile xxxx.json])
|
101
|
+
end
|
102
|
+
|
103
|
+
# space and keyfile filled
|
104
|
+
assert_nothing_raised do
|
105
|
+
create_driver(%[space space\nkeyfile xxxx.json])
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_timezone_configure
|
110
|
+
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
111
|
+
|
112
|
+
d = create_driver(CONFIG + %[localtime])
|
113
|
+
with_timezone('Asia/Tokyo') do
|
114
|
+
assert_equal true, d.instance.localtime
|
115
|
+
assert_equal "07:00:00", d.instance.timef.format(time)
|
116
|
+
end
|
117
|
+
|
118
|
+
d = create_driver(CONFIG + %[utc])
|
119
|
+
with_timezone('Asia/Tokyo') do
|
120
|
+
assert_equal false, d.instance.localtime
|
121
|
+
assert_equal "22:00:00", d.instance.timef.format(time)
|
122
|
+
end
|
123
|
+
|
124
|
+
d = create_driver(CONFIG + %[timezone Asia/Taipei])
|
125
|
+
with_timezone('Asia/Tokyo') do
|
126
|
+
assert_equal "Asia/Taipei", d.instance.timezone
|
127
|
+
assert_equal "06:00:00", d.instance.timef.format(time)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_time_format_configure
|
132
|
+
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
133
|
+
|
134
|
+
d = create_driver(CONFIG + %[time_format %Y/%m/%d %H:%M:%S])
|
135
|
+
with_timezone('Asia/Tokyo') do
|
136
|
+
assert_equal "2014/01/02 07:00:00", d.instance.timef.format(time)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_buffer_configure
|
141
|
+
assert_nothing_raised do
|
142
|
+
create_driver(CONFIG + %[buffer_type file\nbuffer_path tmp/])
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_https_proxy_configure
|
147
|
+
# default
|
148
|
+
d = create_driver(CONFIG)
|
149
|
+
assert_equal nil, d.instance.slack.https_proxy
|
150
|
+
assert_equal Net::HTTP, d.instance.slack.proxy_class
|
151
|
+
|
152
|
+
# https_proxy
|
153
|
+
d = create_driver(CONFIG + %[https_proxy https://proxy.foo.bar:443])
|
154
|
+
assert_equal URI.parse('https://proxy.foo.bar:443'), d.instance.slack.https_proxy
|
155
|
+
assert_not_equal Net::HTTP, d.instance.slack.proxy_class # Net::HTTP.Proxy
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_default_google_chat_api
|
159
|
+
d = create_driver(%[
|
160
|
+
space space
|
161
|
+
keyfile xxxx.json
|
162
|
+
])
|
163
|
+
assert_equal Fluent::SlackClient::WebApi, d.instance.slack.class
|
164
|
+
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
165
|
+
d.tag = 'test'
|
166
|
+
mock(d.instance.google_chat).post_message(default_payload.merge({
|
167
|
+
text: "treasury\nspring\n",
|
168
|
+
}), {})
|
169
|
+
with_timezone('Asia/Tokyo') do
|
170
|
+
d.emit({message: 'treasury'}, time)
|
171
|
+
d.emit({message: 'spring'}, time)
|
172
|
+
d.run
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_plain_payload
|
177
|
+
d = create_driver(CONFIG)
|
178
|
+
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
179
|
+
d.tag = 'test'
|
180
|
+
# attachments field should be changed to show the title
|
181
|
+
mock(d.instance.slack).post_message(default_payload.merge({
|
182
|
+
text: "sowawa1\nsowawa2\n",
|
183
|
+
}), {})
|
184
|
+
with_timezone('Asia/Tokyo') do
|
185
|
+
d.emit({message: 'sowawa1'}, time)
|
186
|
+
d.emit({message: 'sowawa2'}, time)
|
187
|
+
d.run
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def test_message_keys
|
192
|
+
d = create_driver(CONFIG + %[message [%s] %s %s\nmessage_keys time,tag,message])
|
193
|
+
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
194
|
+
d.tag = 'test'
|
195
|
+
mock(d.instance.slack).post_message(default_payload.merge({
|
196
|
+
text: "[07:00:00] test sowawa1\n[07:00:00] test sowawa2\n",
|
197
|
+
}), {})
|
198
|
+
with_timezone('Asia/Tokyo') do
|
199
|
+
d.emit({message: 'sowawa1'}, time)
|
200
|
+
d.emit({message: 'sowawa2'}, time)
|
201
|
+
d.run
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def test_space_keys
|
206
|
+
d = create_driver(CONFIG + %[space %s\nspace_keys space])
|
207
|
+
time = Time.parse("2014-01-01 22:00:00 UTC").to_i
|
208
|
+
d.tag = 'test'
|
209
|
+
mock(d.instance.slack).post_message(default_payload.merge({
|
210
|
+
space: 'space1',
|
211
|
+
text: "treasury\n",
|
212
|
+
}), {})
|
213
|
+
mock(d.instance.slack).post_message(default_payload.merge({
|
214
|
+
space: 'space2',
|
215
|
+
text: "spring\n",
|
216
|
+
}), {})
|
217
|
+
with_timezone('Asia/Tokyo') do
|
218
|
+
d.emit({message: 'treasury', space: 'space1'}, time)
|
219
|
+
d.emit({message: 'spring', space: 'space2'}, time)
|
220
|
+
d.run
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
|
4
|
+
begin
|
5
|
+
Bundler.setup(:default, :development)
|
6
|
+
rescue Bundler::BundlerError => e
|
7
|
+
$stderr.puts e.message
|
8
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
9
|
+
exit e.status_code
|
10
|
+
end
|
11
|
+
require 'test/unit'
|
12
|
+
require 'test/unit/rr'
|
13
|
+
|
14
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
15
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
16
|
+
require 'fluent/test'
|
17
|
+
unless ENV.has_key?('VERBOSE')
|
18
|
+
nulllogger = Object.new
|
19
|
+
nulllogger.instance_eval {|obj|
|
20
|
+
def method_missing(method, *args)
|
21
|
+
# pass
|
22
|
+
end
|
23
|
+
}
|
24
|
+
$log = nulllogger
|
25
|
+
end
|
26
|
+
|
27
|
+
def with_timezone(tz)
|
28
|
+
oldtz, ENV['TZ'] = ENV['TZ'], tz
|
29
|
+
yield
|
30
|
+
ensure
|
31
|
+
ENV['TZ'] = oldtz
|
32
|
+
end
|
data/todelete.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require './lib/fluent/plugin/google_chat_client'
|
2
|
+
|
3
|
+
# API: FluentLogger.new(tag_prefix, options)
|
4
|
+
client = Fluent::GoogleChatClient::WebApi.new("./keyfile.json")
|
5
|
+
message = {text: "Hello", space: "AAAAcmBaNCg"}
|
6
|
+
client.post(message)
|
7
|
+
|
8
|
+
client = Fluent::GoogleChatOutput.new
|
9
|
+
client.write("Hello")
|
10
|
+
# log.post('google_chat', {
|
11
|
+
# :message => 'Hello<br>World!'
|
12
|
+
# })
|
13
|
+
log.warn("some application running.")
|
metadata
ADDED
@@ -0,0 +1,206 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fluent-plugin-google-chat
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Lionel Gabaude
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-06-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: fluentd
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.12.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.12.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: googleauth
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: google-api-client
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.34'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.34'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 10.1.1
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 10.1.1
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rr
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.0.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.0.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry-nav
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: test-unit
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 3.0.2
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 3.0.2
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: test-unit-rr
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 1.0.3
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 1.0.3
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: dotenv
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
description: fluent Google Chat plugin
|
154
|
+
email:
|
155
|
+
- tech@treasuryspring.com
|
156
|
+
executables: []
|
157
|
+
extensions: []
|
158
|
+
extra_rdoc_files: []
|
159
|
+
files:
|
160
|
+
- ".gitignore"
|
161
|
+
- ".travis.yml"
|
162
|
+
- CHANGELOG.md
|
163
|
+
- Gemfile
|
164
|
+
- Gemfile.fluentd.0.12
|
165
|
+
- README.md
|
166
|
+
- Rakefile
|
167
|
+
- VERSION
|
168
|
+
- docker.sh
|
169
|
+
- example.conf
|
170
|
+
- fluent-plugin-google-chat.gemspec
|
171
|
+
- lib/fluent/plugin/google_chat_client.rb
|
172
|
+
- lib/fluent/plugin/google_chat_client/error.rb
|
173
|
+
- lib/fluent/plugin/out_buffered_google_chat.rb
|
174
|
+
- lib/fluent/plugin/out_google_chat.rb
|
175
|
+
- test.sh
|
176
|
+
- test/plugin/test_google_chat_client.rb
|
177
|
+
- test/plugin/test_out_google_chat.rb
|
178
|
+
- test/test_helper.rb
|
179
|
+
- todelete.rb
|
180
|
+
homepage: https://github.com/treasuryspring/fluent-plugin-google-chat
|
181
|
+
licenses:
|
182
|
+
- Apache-2.0
|
183
|
+
metadata: {}
|
184
|
+
post_install_message:
|
185
|
+
rdoc_options: []
|
186
|
+
require_paths:
|
187
|
+
- lib
|
188
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
189
|
+
requirements:
|
190
|
+
- - ">="
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: '0'
|
193
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
194
|
+
requirements:
|
195
|
+
- - ">="
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
version: '0'
|
198
|
+
requirements: []
|
199
|
+
rubygems_version: 3.0.3
|
200
|
+
signing_key:
|
201
|
+
specification_version: 4
|
202
|
+
summary: fluent Google Chat plugin
|
203
|
+
test_files:
|
204
|
+
- test/plugin/test_google_chat_client.rb
|
205
|
+
- test/plugin/test_out_google_chat.rb
|
206
|
+
- test/test_helper.rb
|