fluent-plugin-storage-mongo 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1f92c1ab802709f91b4621de0647a350c57c8083
4
+ data.tar.gz: 3eb59a886d0a1f82b8a4f09b6246f6268f565cb7
5
+ SHA512:
6
+ metadata.gz: a3330e09aac3131c289f47ed84997ec13f309e72a263d89a5386ef6307b6be7413f931ecd73afa95b5ae63ccbdf8a89b9de4333c0d1337baec94eaf151ae4dbd
7
+ data.tar.gz: 940e09ed5c593d8429ea7f30014f9d36fef29daba6543a48bd11f4e16e7a4c23c5b37e3d8036188cf0e86f717e418224e0086d5f6f4092e7ff0cba5b9cb6780a
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /vendor/
11
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1
4
+ - 2.2
5
+ - 2.3.3
6
+ - 2.4.0
7
+
8
+ before_install:
9
+ - gem install bundler
10
+
11
+ script:
12
+ - bundle exec rake test
13
+
14
+ addons:
15
+ apt:
16
+ sources:
17
+ - mongodb-upstart
18
+ - mongodb-3.0-precise
19
+ packages:
20
+ - mongodb-org-server
21
+ - mongodb-org-shell
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-storage-mongo.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Hiroshi Hatake
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,64 @@
1
+ # Mongo Storage plugin for Fluent
2
+
3
+ [![Build Status](https://travis-ci.org/cosmo0920/fluent-plugin-storage-mongo.svg?branch=master)](https://travis-ci.org/cosmo0920/fluent-plugin-storage-mongo)
4
+
5
+ fluent-plugin-storage-mongo is a fluentd plugin to store plugin state into mongodb.
6
+
7
+ ## Prerequisite
8
+
9
+ * MongoDB 3.0 or later.
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'fluent-plugin-storage-mongo'
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install fluent-plugin-storage-mongo
26
+
27
+ ## Configuration
28
+
29
+ Use _mongo_ type in store.
30
+
31
+ ```aconf
32
+ <store>
33
+ @type mongo
34
+ database fluent
35
+ collection test
36
+
37
+ # Following attibutes are optional
38
+ host fluenter
39
+ port 10000
40
+
41
+ # capped option is not implemented yet.
42
+
43
+ # Set 'user' and 'password' for authentication
44
+ user handa
45
+ password shinobu
46
+
47
+ # Other buffer configurations here
48
+ </store>
49
+ ```
50
+
51
+ ## Development
52
+
53
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
54
+
55
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
56
+
57
+ ## Contributing
58
+
59
+ Bug reports and pull requests are welcome on GitHub at https://github.com/cosmo0920/fluent-plugin-storage-mongo.
60
+
61
+
62
+ ## License
63
+
64
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake/testtask'
4
+ Rake::TestTask.new(:test) do |test|
5
+ test.libs << 'lib' << 'test'
6
+ test.pattern = 'test/**/test_*.rb'
7
+ test.verbose = true
8
+ end
9
+
10
+ task default: :test
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "fluent/plugin/storage/mongo"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,37 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "fluent-plugin-storage-mongo"
7
+ spec.version = "0.0.1"
8
+ spec.authors = ["Hiroshi Hatake"]
9
+ spec.email = ["cosmo0920.oucc@gmail.com"]
10
+
11
+ spec.summary = %q{Fluentd storage plugin for MongoDB.}
12
+ spec.description = %q{Fluentd storage plugin for MongoDB.}
13
+ spec.homepage = "https://github.com/cosmo0920/fluent-plugin-storage-mongo"
14
+ spec.license = "MIT"
15
+
16
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
17
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
18
+ if spec.respond_to?(:metadata)
19
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
20
+ else
21
+ raise "RubyGems 2.0 or newer is required to protect against " \
22
+ "public gem pushes."
23
+ end
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
26
+ f.match(%r{^(test|spec|features)/})
27
+ end
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ spec.add_development_dependency "bundler", "~> 1.13"
33
+ spec.add_development_dependency "rake", "~> 12.0"
34
+ spec.add_development_dependency "test-unit", "~> 3.2.0"
35
+ spec.add_dependency "fluentd", [">= 0.14.12", "< 2"]
36
+ spec.add_dependency "mongo", "~> 2.4.0"
37
+ end
@@ -0,0 +1,25 @@
1
+ module Fluent::Plugin
2
+ module LoggerSupport
3
+ def self.included(klass)
4
+ klass.instance_eval {
5
+ desc "MongoDB log level"
6
+ config_param :mongo_log_level, :string, default: 'info'
7
+ }
8
+ end
9
+
10
+ def configure_logger(mongo_log_level)
11
+ Mongo::Logger.level = case @mongo_log_level.downcase
12
+ when 'fatal'
13
+ Logger::FATAL
14
+ when 'error'
15
+ Logger::ERROR
16
+ when 'warn'
17
+ Logger::WARN
18
+ when 'info'
19
+ Logger::INFO
20
+ when 'debug'
21
+ Logger::DEBUG
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,34 @@
1
+ module Fluent
2
+ module Plugin
3
+ module MongoAuthParams
4
+ def self.included(klass)
5
+ klass.instance_eval {
6
+ desc "MongoDB user"
7
+ config_param :user, :string, default: nil
8
+ desc "MongoDB password"
9
+ config_param :password, :string, default: nil, secret: true
10
+ desc "MongoDB authentication database"
11
+ config_param :auth_source, :string, default: nil
12
+ }
13
+ end
14
+ end
15
+
16
+ module MongoAuth
17
+ def authenticate(client)
18
+ unless @user.nil? || @password.nil?
19
+ begin
20
+ if @auth_source.nil?
21
+ client = client.with(user: @user, password: @password)
22
+ else
23
+ client = client.with(user: @user, password: @password, auth_source: @auth_source)
24
+ end
25
+ rescue Mongo::Auth::Unauthorized => e
26
+ log.fatal e
27
+ exit!
28
+ end
29
+ end
30
+ client
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,196 @@
1
+ require 'mongo'
2
+ require 'fluent/plugin/storage'
3
+ require 'fluent/plugin/mongo_auth'
4
+ require 'fluent/plugin/logger_support'
5
+
6
+ module Fluent
7
+ module Plugin
8
+ class MongoStorage < Storage
9
+ Fluent::Plugin.register_storage('mongo', self)
10
+
11
+ attr_reader :store # for test
12
+
13
+ include Fluent::Plugin::MongoAuthParams
14
+ include Fluent::Plugin::MongoAuth
15
+ include Fluent::Plugin::LoggerSupport
16
+
17
+ config_param :path, :string, default: nil
18
+ desc "MongoDB collection"
19
+ config_param :collection, :string, default: "unspecified"
20
+ desc "MongoDB database"
21
+ config_param :database, :string
22
+ desc "MongoDB host"
23
+ config_param :host, :string, default: 'localhost'
24
+ desc "MongoDB port"
25
+ config_param :port, :integer, default: 27017
26
+ desc "MongoDB write_concern"
27
+ config_param :write_concern, :integer, default: nil
28
+ desc "MongoDB journaled"
29
+ config_param :journaled, :bool, default: false
30
+ desc "Replace dot with specified string"
31
+ config_param :replace_dot_in_key_with, :string, default: nil
32
+ desc "Replace dollar with specified string"
33
+ config_param :replace_dollar_in_key_with, :string, default: nil
34
+
35
+ # SSL connection
36
+ config_param :ssl, :bool, default: false
37
+ config_param :ssl_cert, :string, default: nil
38
+ config_param :ssl_key, :string, default: nil
39
+ config_param :ssl_key_pass_phrase, :string, default: nil, secret: true
40
+ config_param :ssl_verify, :bool, default: false
41
+ config_param :ssl_ca_cert, :string, default: nil
42
+
43
+ attr_reader :client_options, :collection_options
44
+
45
+ def initialize
46
+ super
47
+
48
+ @client_options = {}
49
+ @collection_options = {capped: false}
50
+ @store = {}
51
+ end
52
+
53
+ def configure(conf)
54
+ super
55
+
56
+ unless @path
57
+ if conf && !conf.arg.empty?
58
+ @path = conf.arg
59
+ else
60
+ raise Fluent::ConfigError, "path or conf.arg for <storage> is required."
61
+ end
62
+ end
63
+
64
+ @client_options[:write] = {j: @journaled}
65
+ @client_options[:write].merge!({w: @write_concern}) unless @write_concern.nil?
66
+ @client_options[:ssl] = @ssl
67
+
68
+ if @ssl
69
+ @client_options[:ssl_cert] = @ssl_cert
70
+ @client_options[:ssl_key] = @ssl_key
71
+ @client_options[:ssl_key_pass_phrase] = @ssl_key_pass_phrase
72
+ @client_options[:ssl_verify] = @ssl_verify
73
+ @client_options[:ssl_ca_cert] = @ssl_ca_cert
74
+ end
75
+ configure_logger(@mongo_log_level)
76
+
77
+ @client = client
78
+ @client = authenticate(@client)
79
+ end
80
+
81
+ def multi_workers_ready?
82
+ true
83
+ end
84
+
85
+ def load
86
+ begin
87
+ value = {}
88
+ documents = @client[format_collection_name(@collection)].find(_id: @path)
89
+ if documents.count >= 1
90
+ documents.each do |document|
91
+ value.merge!(document)
92
+ end
93
+ end
94
+ value.delete('_id')
95
+ unless value.is_a?(Hash)
96
+ log.error "broken content for plugin storage (Hash required: ignored)", type: json.class
97
+ log.debug "broken content", content: json_string
98
+ return
99
+ end
100
+ @store = value
101
+ rescue => e
102
+ log.error "failed to load data for plugin storage from mongo", path: @path, error: e
103
+ end
104
+ end
105
+
106
+ def save
107
+ operate(format_collection_name(@collection), @store)
108
+ end
109
+
110
+ def get(key)
111
+ @store[key.to_s]
112
+ end
113
+
114
+ def fetch(key, defval)
115
+ @store.fetch(key.to_s, defval)
116
+ end
117
+
118
+ def put(key, value)
119
+ @store[key.to_s] = value
120
+ end
121
+
122
+ def delete(key)
123
+ @store.delete(key.to_s)
124
+ end
125
+
126
+ def update(key, &block)
127
+ @store[key.to_s] = block.call(@store[key.to_s])
128
+ end
129
+
130
+ private
131
+
132
+ def client
133
+ @client_options[:database] = @database
134
+ @client_options[:user] = @user if @user
135
+ @client_options[:password] = @password if @password
136
+ Mongo::Client.new(["#{@host}:#{@port}"], @client_options)
137
+ end
138
+
139
+ FORMAT_COLLECTION_NAME_RE = /(^\.+)|(\.+$)/
140
+
141
+ def format_collection_name(collection_name)
142
+ formatted = collection_name
143
+ formatted = formatted.gsub(FORMAT_COLLECTION_NAME_RE, '')
144
+ formatted = @collection if formatted.size == 0 # set default for nil tag
145
+ formatted
146
+ end
147
+
148
+ def format_key(record)
149
+ if @replace_dot_in_key_with
150
+ replace_key_of_hash(record, ".", @replace_dot_in_key_with)
151
+ end
152
+ if @replace_dollar_in_key_with
153
+ replace_key_of_hash(record, /^\$/, @replace_dollar_in_key_with)
154
+ end
155
+ record
156
+ end
157
+
158
+ def operate(collection, record)
159
+ begin
160
+ record = format_key(record)
161
+
162
+ @client[collection, @collection_options].update_one({_id: @path}, record, {upsert: true})
163
+ rescue Mongo::Error::BulkWriteError => e
164
+ log.warn "document is not inserted. Maybe this document is invalid as a BSON."
165
+ rescue ArgumentError => e
166
+ log.warn e
167
+ end
168
+ record
169
+ end
170
+
171
+ # copied from https://github.com/fluent/fluent-plugin-mongo/blob/c989ae01d21513c8d45b5338431586542aa93b0d/lib/fluent/plugin/out_mongo.rb#L223-L244
172
+ def replace_key_of_hash(hash_or_array, pattern, replacement)
173
+ case hash_or_array
174
+ when Array
175
+ hash_or_array.map do |elm|
176
+ replace_key_of_hash(elm, pattern, replacement)
177
+ end
178
+ when Hash
179
+ result = Hash.new
180
+ hash_or_array.each_pair do |k, v|
181
+ k = k.gsub(pattern, replacement)
182
+
183
+ if v.is_a?(Hash) || v.is_a?(Array)
184
+ result[k] = replace_key_of_hash(v, pattern, replacement)
185
+ else
186
+ result[k] = v
187
+ end
188
+ end
189
+ result
190
+ else
191
+ hash_or_array
192
+ end
193
+ end
194
+ end
195
+ end
196
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-storage-mongo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Hiroshi Hatake
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-02-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.13'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.13'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '12.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '12.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: test-unit
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.2.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.2.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: fluentd
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 0.14.12
62
+ - - "<"
63
+ - !ruby/object:Gem::Version
64
+ version: '2'
65
+ type: :runtime
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: 0.14.12
72
+ - - "<"
73
+ - !ruby/object:Gem::Version
74
+ version: '2'
75
+ - !ruby/object:Gem::Dependency
76
+ name: mongo
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: 2.4.0
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: 2.4.0
89
+ description: Fluentd storage plugin for MongoDB.
90
+ email:
91
+ - cosmo0920.oucc@gmail.com
92
+ executables: []
93
+ extensions: []
94
+ extra_rdoc_files: []
95
+ files:
96
+ - ".gitignore"
97
+ - ".travis.yml"
98
+ - Gemfile
99
+ - LICENSE.txt
100
+ - README.md
101
+ - Rakefile
102
+ - bin/console
103
+ - bin/setup
104
+ - fluent-plugin-storage-mongo.gemspec
105
+ - lib/fluent/plugin/logger_support.rb
106
+ - lib/fluent/plugin/mongo_auth.rb
107
+ - lib/fluent/plugin/storage_mongo.rb
108
+ homepage: https://github.com/cosmo0920/fluent-plugin-storage-mongo
109
+ licenses:
110
+ - MIT
111
+ metadata:
112
+ allowed_push_host: https://rubygems.org
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubyforge_project:
129
+ rubygems_version: 2.6.8
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: Fluentd storage plugin for MongoDB.
133
+ test_files: []