fluent-plugin-openstack 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9b33942f008ad19c796f4454ba2e9176ab90dc7f43e974f9dda81d6201a4ec3d
4
+ data.tar.gz: c2414c02db5bebd37f5ed9103a9a25f9f836a5de3037002580fb7ee5f399cf6b
5
+ SHA512:
6
+ metadata.gz: 2ac64444f46c298403798f7c74fc4f92d52cd4b57b0ee4f214e5dd2f4cc1898c1344f9564802b54c5c1c11eff644c16fe9f4e1b38b339d8aebbcc65dbb99e2e2
7
+ data.tar.gz: 1d9b1df6f12088f51d7aed52fd08aa0b7a2a847535cea83439551fad4904ab9ad2b893f613184a7574f1ec1d662e395c32b8e095df57a211a71dabfbbfc27691
@@ -0,0 +1,13 @@
1
+ ~*
2
+ #*
3
+ *~
4
+ [._]*.s[a-w][a-z]
5
+ .DS_Store
6
+
7
+ *.gem
8
+ .bundle
9
+ Gemfile.lock
10
+ vendor
11
+ .ruby-version
12
+
13
+ test/tmp/
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
@@ -0,0 +1,7 @@
1
+ Copyright 2019 robert.krzysztoforski@protonmail.com
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,6 @@
1
+ ## OpenStack Storage Service (Swift) plugin for Fluent
2
+
3
+ ### Overview
4
+
5
+ This gem is based on hard work of: `https://github.com/yuuzi41/fluent-plugin-openstack`.
6
+ It is simplified and refactored version of this gem.
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ require 'rake/testtask'
7
+
8
+ Rake::TestTask.new(:test) do |t|
9
+ t.libs.push('lib', 'test')
10
+ t.test_files = FileList['test/**/test_*.rb']
11
+ t.verbose = true
12
+ t.warning = false
13
+ end
14
+
15
+ task default: [:test]
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.2
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.push File.expand_path('lib', __dir__)
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = 'fluent-plugin-openstack'
7
+ gem.description = 'OpenStack Storage Service (Swift) plugin for Fluentd'
8
+ gem.homepage = 'https://github.com/jnsolutions/fluent-plugin-openstack'
9
+ gem.summary = gem.description
10
+ gem.version = File.read('VERSION').strip
11
+ gem.license = 'MIT'
12
+ gem.authors = ['brissenden']
13
+ gem.email = 'robert.krzysztoforski@protonmail.com'
14
+ gem.platform = Gem::Platform::RUBY
15
+ gem.files = `git ls-files`.split("\n")
16
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
18
+ gem.require_paths = ['lib']
19
+
20
+ gem.add_runtime_dependency 'fluentd', ['>= 0.14.2', '< 2']
21
+ gem.add_runtime_dependency 'fog-openstack'
22
+ gem.add_runtime_dependency 'uuidtools'
23
+
24
+ gem.add_development_dependency 'bundler', '~> 2.0.2'
25
+ gem.add_development_dependency 'flexmock', '>= 1.2.0'
26
+ gem.add_development_dependency 'rake', '~> 12.0'
27
+ gem.add_development_dependency 'test-unit', '>= 3.1.0'
28
+
29
+ gem.add_dependency('xmlrpc') if RUBY_VERSION.to_s >= '2.4'
30
+ end
@@ -0,0 +1,314 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fluent/plugin/output'
4
+ require 'fluent/timezone'
5
+ require 'fog/openstack'
6
+ require 'zlib'
7
+ require 'time'
8
+ require 'tempfile'
9
+ require 'open3'
10
+
11
+ module Fluent::Plugin
12
+ class SwiftOutput < Output
13
+ Fluent::Plugin.register_output('swift', self)
14
+
15
+ DEFAULT_FORMAT_TYPE = 'out_file'
16
+ MAX_HEX_RANDOM_LENGTH = 16
17
+
18
+ desc 'Path prefix of the files on Swift'
19
+ config_param :path, :string, default: ''
20
+ # OpenStack AUTH
21
+ desc "Authentication URL. Set a value or `#{ENV['OS_AUTH_URL']}`"
22
+ config_param :auth_url, :string
23
+ desc "Authentication User Name. If you use TempAuth, auth_user is ACCOUNT:USER. Set a value or use `#{ENV['OS_USERNAME']}`"
24
+ config_param :auth_user, :string
25
+ desc "Authentication Key (Password). Set a value or use `#{ENV['OS_PASSWORD']}`"
26
+ config_param :auth_api_key, :string
27
+ # Identity v2
28
+ config_param :auth_tenant, :string, default: nil
29
+ # Identity v3
30
+ desc "Authentication Project. Set a value or use `#{ENV['OS_PROJECT_NAME']}`"
31
+ config_param :project_name, :string, default: nil
32
+ desc "Authentication Domain. Set a value or use `#{ENV['OS_PROJECT_DOMAIN_NAME']}`"
33
+ config_param :domain_name, :string, default: nil
34
+ desc "Authentication Region. Optional, not required if there is only one region available. Set a value or use `#{ENV['OS_REGION_NAME']}`"
35
+ config_param :auth_region, :string, default: nil
36
+ config_param :swift_account, :string, default: nil
37
+
38
+ desc 'Swift container name'
39
+ config_param :swift_container, :string
40
+ desc 'Archive format on Swift'
41
+ config_param :store_as, :string, default: 'gzip'
42
+ desc 'If false, the certificate of endpoint will not be verified'
43
+ config_param :ssl_verify, :bool, default: true
44
+ desc 'The format of Swift object keys'
45
+ config_param :swift_object_key_format, :string, default: '%{path}%{time_slice}_%{index}.%{file_extension}'
46
+ desc 'Create Swift container if it does not exists'
47
+ config_param :auto_create_container, :bool, default: true
48
+ config_param :check_apikey_on_start, :bool, default: true
49
+ desc 'URI of proxy environment'
50
+ config_param :proxy_uri, :string, default: nil
51
+ desc 'The length of `%{hex_random}` placeholder(4-16)'
52
+ config_param :hex_random_length, :integer, default: 4
53
+ desc '`sprintf` format for `%{index}`'
54
+ config_param :index_format, :string, default: '%d'
55
+ desc 'Overwrite already existing path'
56
+ config_param :overwrite, :bool, default: false
57
+
58
+ config_section :format do
59
+ config_set_default :@type, DEFAULT_FORMAT_TYPE
60
+ end
61
+
62
+ config_section :buffer do
63
+ config_set_default :chunk_keys, ['time']
64
+ config_set_default :timekey, (60 * 60 * 24)
65
+ end
66
+
67
+ helpers :compat_parameters, :formatter, :inject
68
+
69
+ def initialize
70
+ super
71
+ self.uuid_flush_enabled = false
72
+ end
73
+
74
+ def configure(config)
75
+ compat_parameters_convert(config, :buffer, :formatter, :inject)
76
+
77
+ super
78
+
79
+ if auth_url.blank?
80
+ raise Fluent::ConfigError, 'auth_url parameter or OS_AUTH_URL variable not defined'
81
+ end
82
+ if auth_user.blank?
83
+ raise Fluent::ConfigError, 'auth_user parameter or OS_USERNAME variable not defined'
84
+ end
85
+ if auth_api_key.blank?
86
+ raise Fluent::ConfigError, 'auth_api_key parameter or OS_PASSWORD variable not defined'
87
+ end
88
+
89
+ if project_name.blank?
90
+ raise Fluent::ConfigError, 'project_name parameter or OS_PROJECT_NAME variable not defined'
91
+ end
92
+ if domain_name.blank?
93
+ raise Fluent::ConfigError, 'domain_name parameter or OS_PROJECT_DOMAIN_NAME variable not defined'
94
+ end
95
+
96
+ self.ext, self.mime_type = case store_as
97
+ when 'gzip' then ['gz', 'application/x-gzip']
98
+ when 'lzo' then
99
+ begin
100
+ Open3.capture3('lzop -V')
101
+ rescue Errno::ENOENT
102
+ raise ConfigError, "'lzop' utility must be in PATH for LZO compression"
103
+ end
104
+ ['lzo', 'application/x-lzop']
105
+ when 'json' then ['json', 'application/json']
106
+ else ['txt', 'text/plain']
107
+ end
108
+
109
+ self.formatter = formatter_create
110
+
111
+ if hex_random_length > MAX_HEX_RANDOM_LENGTH
112
+ raise Fluent::ConfigError, "hex_random_length parameter must be less than or equal to #{MAX_HEX_RANDOM_LENGTH}"
113
+ end
114
+
115
+ unless index_format =~ /^%(0\d*)?[dxX]$/
116
+ raise Fluent::ConfigError, 'index_format parameter should follow `%[flags][width]type`. `0` is the only supported flag, and is mandatory if width is specified. `d`, `x` and `X` are supported types'
117
+ end
118
+
119
+ self.swift_object_key_format = configure_swift_object_key_format
120
+ # For backward compatibility
121
+ # TODO: Remove time_slice_format when end of support compat_parameters
122
+ self.values_for_swift_object_chunk = {}
123
+ self.time_slice_with_tz = Fluent::Timezone.formatter(timekey_zone, config['time_slice_format'] || timekey_to_timeformat(timekey: buffer_config['timekey']))
124
+ end
125
+
126
+ def multi_workers_ready?
127
+ true
128
+ end
129
+
130
+ def start
131
+ Excon.defaults[:ssl_verify_peer] = ssl_verify
132
+ begin
133
+ self.storage = Fog::Storage.new(
134
+ provider: 'OpenStack',
135
+ openstack_auth_url: auth_url,
136
+ openstack_username: auth_user,
137
+ openstack_api_key: auth_api_key,
138
+ openstack_tenant: auth_tenant,
139
+ openstack_project_name: project_name,
140
+ openstack_domain_name: domain_name,
141
+ openstack_region: auth_region
142
+ )
143
+ rescue StandardError => exp
144
+ raise "Can't call Swift API. Please check your ENV OS_*, your credentials or auth_url configuration. Error: #{exp.inspect}"
145
+ end
146
+ if swift_account
147
+ storage.change_account(swift_account)
148
+ end
149
+ check_container
150
+ super
151
+ end
152
+
153
+ # TODO: dead method?
154
+ def format(tag, time, record)
155
+ r = inject_values_to_record(tag, time, record)
156
+ formatter.format(tag, time, r)
157
+ end
158
+
159
+ def write(chunk)
160
+ i = 0
161
+ metadata = chunk.metadata
162
+ previous_path = nil
163
+ time_slice = if metadata.timekey.nil?
164
+ ''
165
+ else
166
+ time_slice_with_tz.call(metadata.timekey)
167
+ end
168
+
169
+ while check_object_exists(object: swift_path)
170
+ values_for_swift_object_chunk[chunk.unique_id] ||= {
171
+ '%{hex_random}' => hex_random(chunk: chunk)
172
+ }
173
+ values_for_swift_object_key_pre = {
174
+ '%{path}' => path,
175
+ '%{file_extension}' => ext
176
+ }
177
+ values_for_swift_object_key_post = {
178
+ '%{time_slice}' => time_slice,
179
+ '%{index}' => format(index_format, i)
180
+ }.merge!(values_for_swift_object_chunk[chunk.unique_id])
181
+ values_for_swift_object_key_post['%{uuid_flush}'] = uuid_random if uuid_flush_enabled
182
+
183
+ swift_path = swift_object_key_format.gsub(/%{[^}]+}/) do |matched_key|
184
+ values_for_swift_object_key_pre.fetch(matched_key, matched_key)
185
+ end
186
+
187
+ swift_path = extract_placeholders(swift_path, metadata)
188
+ swift_path = swift_path.gsub(/%{[^}]+}/, values_for_swift_object_key_post)
189
+ if (i > 0) && (swift_path == previous_path)
190
+ if overwrite
191
+ log.warn "#{swift_path} already exists, but will overwrite"
192
+ break
193
+ else
194
+ raise "duplicated path is generated. use %{index} in swift_object_key_format: path = #{swift_path}"
195
+ end
196
+ end
197
+
198
+ i += 1
199
+ previous_path = swift_path
200
+ end
201
+
202
+ tmp = Tempfile.new('swift-')
203
+ tmp.binmode
204
+ begin
205
+ if store_as == 'gzip'
206
+ w = Zlib::GzipWriter.new(tmp)
207
+ chunk.write_to(w)
208
+ w.close
209
+ elsif store_as == 'lzo'
210
+ w = Tempfile.new('chunk-tmp')
211
+ chunk.write_to(w)
212
+ w.close
213
+ tmp.close
214
+ system "lzop -qf1 -o #{tmp.path} #{w.path}"
215
+ else
216
+ chunk.write_to(tmp)
217
+ tmp.close
218
+ end
219
+ File.open(tmp.path) do |file|
220
+ storage.put_object(swift_container, swift_path, file, content_type: mime_type)
221
+ values_for_swift_object_chunk.delete(chunk.unique_id)
222
+ end
223
+ ensure
224
+ begin
225
+ tmp.close(true)
226
+ rescue StandardError
227
+ nil
228
+ end
229
+ begin
230
+ w.close
231
+ rescue StandardError
232
+ nil
233
+ end
234
+ begin
235
+ w.unlink
236
+ rescue StandardError
237
+ nil
238
+ end
239
+ end
240
+ end
241
+
242
+ private
243
+
244
+ attr_accessor :uuid_flush_enabled, :storage, :ext, :mime_type, :formatter, :values_for_swift_object_chunk, :time_slice_with_tz
245
+
246
+ def hex_random(chunk:)
247
+ unique_hex = Fluent::UniqueId.hex(chunk.unique_id)
248
+ unique_hex.reverse!
249
+ unique_hex[0...hex_random_length]
250
+ end
251
+
252
+ def uuid_random
253
+ ::UUIDTools::UUID.random_create.to_s
254
+ end
255
+
256
+ # This is stolen from Fluentd
257
+ def timekey_to_timeformat(timekey:)
258
+ case timekey
259
+ when nil then ''
260
+ when 0...60 then '%Y%m%d%H%M%S'
261
+ when 60...3600 then '%Y%m%d%H%M'
262
+ when 3600...86_400 then '%Y%m%d%H'
263
+ else '%Y%m%d'
264
+ end
265
+ end
266
+
267
+ def check_container
268
+ storage.get_container(swift_container)
269
+ rescue Fog::OpenStack::Storage::NotFound
270
+ if auto_create_container
271
+ $log.info "Creating container #{swift_container} on #{auth_url}, #{swift_account}"
272
+ storage.put_container(swift_container)
273
+ else
274
+ raise "The specified container does not exist: container = #{swift_container}"
275
+ end
276
+ end
277
+
278
+ def configure_swift_object_key_format
279
+ %w[%{uuid} %{uuid:random} %{uuid:hostname} %{uuid:timestamp}].each do |ph|
280
+ if swift_object_key_format.include?(ph)
281
+ raise Fluent::ConfigError, %(#{ph} placeholder in swift_object_key_format is removed)
282
+ end
283
+ end
284
+
285
+ if swift_object_key_format.include?('%{uuid_flush}')
286
+ begin
287
+ require 'uuidtools'
288
+ rescue LoadError
289
+ raise Fluent::ConfigError, 'uuidtools gem not found. Install uuidtools gem first'
290
+ end
291
+ begin
292
+ uuid_random
293
+ rescue StandardError => e
294
+ raise Fluent::ConfigError, "Generating uuid doesn't work. Can't use %{uuid_flush} on this environment. #{e}"
295
+ end
296
+ self.uuid_flush_enabled = true
297
+ end
298
+
299
+ swift_object_key_format.gsub('%{hostname}') do |_expr|
300
+ log.warn "%{hostname} will be removed in the future. Use \"\#{Socket.gethostname}\" instead"
301
+ Socket.gethostname
302
+ end
303
+ end
304
+
305
+ def check_object_exists(object:)
306
+ begin
307
+ storage.head_object(swift_container, object)
308
+ true
309
+ rescue Fog::OpenStack::Storage::NotFound
310
+ false
311
+ end
312
+ end
313
+ end
314
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.unshift(File.expand_path('..', __dir__))
4
+ require 'test-unit'
5
+ require 'fluent/test'
6
+ require 'fluent/test/driver/output'
7
+ require 'fluent/test/helpers'
8
+
9
+ Test::Unit::TestCase.include(Fluent::Test::Helpers)
10
+ Test::Unit::TestCase.extend(Fluent::Test::Helpers)
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'helper'
4
+ require 'fluent/plugin/out_swift'
5
+
6
+ class SwiftOutputTest < Test::Unit::TestCase
7
+ setup do
8
+ Fluent::Test.setup
9
+ end
10
+
11
+ def teardown
12
+ Dir.glob('test/tmp/*').each { |file| FileUtils.rm_f(file) }
13
+ end
14
+
15
+ CONFIG_NONE = %(
16
+ swift_container CONTAINER_NAME
17
+ )
18
+
19
+ CONFIG_ENV = %(
20
+ swift_container CONTAINER_NAME
21
+ auth_url "#{ENV['EMPTY_OS_AUTH_URL']}"
22
+ auth_user test:tester
23
+ auth_api_key testing
24
+ )
25
+
26
+ CONFIG = %(
27
+ auth_url https://127.0.0.1/auth/v3
28
+ auth_user test:tester
29
+ auth_api_key testing
30
+ domain_name default
31
+ project_name test_project
32
+ auth_region RegionOne
33
+ swift_container CONTAINER_NAME
34
+ path logs/
35
+ swift_object_key_format %{path}%{time_slice}_%{index}.%{file_extension}
36
+ ssl_verify false
37
+ buffer_path /var/log/fluent/swift
38
+ buffer_type memory
39
+ time_slice_format %Y%m%d-%H
40
+ time_slice_wait 10m
41
+ utc
42
+ )
43
+
44
+ def create_driver(conf = CONFIG)
45
+ Fluent::Test::Driver::Output.new(Fluent::Plugin::SwiftOutput) do
46
+ def format(tag, time, record)
47
+ super
48
+ end
49
+
50
+ def write(chunk)
51
+ chunk.read
52
+ end
53
+
54
+ private
55
+
56
+ def check_container; end
57
+ end.configure(conf)
58
+ end
59
+
60
+ def test_auth_url_absent
61
+ assert_raise_message(/'auth_url' parameter is required/) do
62
+ create_driver(CONFIG_NONE)
63
+ end
64
+ end
65
+
66
+ def test_auth_url_empty
67
+ assert_raise_message(/auth_url parameter or OS_AUTH_URL variable not defined/) do
68
+ create_driver(CONFIG_ENV)
69
+ end
70
+ end
71
+
72
+ def test_configure
73
+ d = create_driver(CONFIG)
74
+ assert_equal 'test:tester', d.instance.auth_user
75
+ assert_equal 'testing', d.instance.auth_api_key
76
+ assert_equal 'RegionOne', d.instance.auth_region
77
+ assert_equal 'CONTAINER_NAME', d.instance.swift_container
78
+ assert_equal 'logs/', d.instance.path
79
+ end
80
+ end
metadata ADDED
@@ -0,0 +1,172 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-openstack
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - brissenden
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-08-28 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.14.2
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '2'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 0.14.2
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2'
33
+ - !ruby/object:Gem::Dependency
34
+ name: fog-openstack
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: uuidtools
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: bundler
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: 2.0.2
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: 2.0.2
75
+ - !ruby/object:Gem::Dependency
76
+ name: flexmock
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: 1.2.0
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: 1.2.0
89
+ - !ruby/object:Gem::Dependency
90
+ name: rake
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '12.0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '12.0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: test-unit
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: 3.1.0
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: 3.1.0
117
+ - !ruby/object:Gem::Dependency
118
+ name: xmlrpc
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ type: :runtime
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ description: OpenStack Storage Service (Swift) plugin for Fluentd
132
+ email: robert.krzysztoforski@protonmail.com
133
+ executables: []
134
+ extensions: []
135
+ extra_rdoc_files: []
136
+ files:
137
+ - ".gitignore"
138
+ - Gemfile
139
+ - LICENSE.md
140
+ - README.md
141
+ - Rakefile
142
+ - VERSION
143
+ - fluent-plugin-openstack.gemspec
144
+ - lib/fluent/plugin/out_swift.rb
145
+ - test/helper.rb
146
+ - test/plugin/test_out_swift.rb
147
+ homepage: https://github.com/jnsolutions/fluent-plugin-openstack
148
+ licenses:
149
+ - MIT
150
+ metadata: {}
151
+ post_install_message:
152
+ rdoc_options: []
153
+ require_paths:
154
+ - lib
155
+ required_ruby_version: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ required_rubygems_version: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - ">="
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ requirements: []
166
+ rubygems_version: 3.0.6
167
+ signing_key:
168
+ specification_version: 4
169
+ summary: OpenStack Storage Service (Swift) plugin for Fluentd
170
+ test_files:
171
+ - test/helper.rb
172
+ - test/plugin/test_out_swift.rb