logstash-input-gcp_storage 0.1.0

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: a9ad9a52f0a8f869cd976ce24a2f69f914d3e0e5179b605d9adce037563e01a1
4
+ data.tar.gz: 6cd20be8e3b29575d80e09bd7e6e5eb71d31188a8de11952a3fb30d6699d392c
5
+ SHA512:
6
+ metadata.gz: adf4a10f98616f47b563de4c5e9c07438dc35310ac4a6edeb516c53e626e0e90d28515fbb5fcfa7b250da4c3e2659dbce43dcc126dca87304dba4cb9d62171f1
7
+ data.tar.gz: b63e572f9d38f8c1b31972f664938d222300ffcda1dc9a8d6d5bcf5ad59ce1a743122e37ba4ebf08526d6780a8f812162d2c2206ae43e437c7a75f6fdc7e4dce
@@ -0,0 +1,2 @@
1
+ ## 0.1.0
2
+ - Plugin created with the logstash plugin generator
@@ -0,0 +1,10 @@
1
+ The following is a list of people who have contributed ideas, code, bug
2
+ reports, or in general have helped logstash along its way.
3
+
4
+ Contributors:
5
+ *jashchahal - jashchahal@gmail.com
6
+
7
+ Note: If you've sent us patches, bug reports, or otherwise contributed to
8
+ Logstash, and you aren't on the list above and want to be, please let us know
9
+ and we'll make sure you're here. Contributions from folks like you are what make
10
+ open source awesome.
@@ -0,0 +1,2 @@
1
+ # logstash-input-google_cloud_storage
2
+ Example input plugin. This should help bootstrap your effort to write your own input plugin!
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
data/LICENSE ADDED
@@ -0,0 +1,11 @@
1
+ Licensed under the Apache License, Version 2.0 (the "License");
2
+ you may not use this file except in compliance with the License.
3
+ You may obtain a copy of the License at
4
+
5
+ http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software
8
+ distributed under the License is distributed on an "AS IS" BASIS,
9
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ See the License for the specific language governing permissions and
11
+ limitations under the License.
@@ -0,0 +1,86 @@
1
+ # Logstash Plugin
2
+
3
+ This is a plugin for [Logstash](https://github.com/elastic/logstash).
4
+
5
+ It is fully free and fully open source. The license is Apache 2.0, meaning you are pretty much free to use it however you want in whatever way.
6
+
7
+ ## Documentation
8
+
9
+ Logstash provides infrastructure to automatically generate documentation for this plugin. We use the asciidoc format to write documentation so any comments in the source code will be first converted into asciidoc and then into html. All plugin documentation are placed under one [central location](http://www.elastic.co/guide/en/logstash/current/).
10
+
11
+ - For formatting code or config example, you can use the asciidoc `[source,ruby]` directive
12
+ - For more asciidoc formatting tips, see the excellent reference here https://github.com/elastic/docs#asciidoc-guide
13
+
14
+ ## Need Help?
15
+
16
+ Need help? Try #logstash on freenode IRC or the https://discuss.elastic.co/c/logstash discussion forum.
17
+
18
+ ## Developing
19
+
20
+ ### 1. Plugin Developement and Testing
21
+
22
+ #### Code
23
+ - To get started, you'll need JRuby with the Bundler gem installed.
24
+
25
+ - Create a new plugin or clone and existing from the GitHub [logstash-plugins](https://github.com/logstash-plugins) organization. We also provide [example plugins](https://github.com/logstash-plugins?query=example).
26
+
27
+ - Install dependencies
28
+ ```sh
29
+ bundle install
30
+ ```
31
+
32
+ #### Test
33
+
34
+ - Update your dependencies
35
+
36
+ ```sh
37
+ bundle install
38
+ ```
39
+
40
+ - Run tests
41
+
42
+ ```sh
43
+ bundle exec rspec
44
+ ```
45
+
46
+ ### 2. Running your unpublished Plugin in Logstash
47
+
48
+ #### 2.1 Run in a local Logstash clone
49
+
50
+ - Edit Logstash `Gemfile` and add the local plugin path, for example:
51
+ ```ruby
52
+ gem "logstash-input-awesome", :path => "/your/local/logstash-input-awesome"
53
+ ```
54
+ - Install plugin
55
+ ```sh
56
+ bin/logstash-plugin install --no-verify
57
+ ```
58
+ - Run Logstash with your plugin
59
+ ```sh
60
+ bin/logstash -e 'input {awesome {}}'
61
+ ```
62
+ At this point any modifications to the plugin code will be applied to this local Logstash setup. After modifying the plugin, simply rerun Logstash.
63
+
64
+ #### 2.2 Run in an installed Logstash
65
+
66
+ You can use the same **2.1** method to run your plugin in an installed Logstash by editing its `Gemfile` and pointing the `:path` to your local plugin development directory or you can build the gem and install it using:
67
+
68
+ - Build your plugin gem
69
+ ```sh
70
+ gem build logstash-input-awesome.gemspec
71
+ ```
72
+ - Install the plugin from the Logstash home
73
+ ```sh
74
+ bin/logstash-plugin install /your/local/plugin/logstash-input-awesome.gem
75
+ ```
76
+ - Start Logstash and proceed to test the plugin
77
+
78
+ ## Contributing
79
+
80
+ All contributions are welcome: ideas, patches, documentation, bug reports, complaints, and even something you drew up on a napkin.
81
+
82
+ Programming is not a required skill. Whatever you've seen about open source and maintainers or community members saying "send patches or die" - you will not see that here.
83
+
84
+ It is more important to the community that you are able to contribute.
85
+
86
+ For more information about contributing, see the [CONTRIBUTING](https://github.com/elastic/logstash/blob/master/CONTRIBUTING.md) file.
@@ -0,0 +1,432 @@
1
+ # encoding: utf-8
2
+ require "logstash/inputs/base"
3
+ require "logstash/namespace"
4
+ require "stud/interval"
5
+ require "socket" # for Socket.gethostname
6
+
7
+ # Generate a repeating message.
8
+ #
9
+ # This plugin is intented only as an example.
10
+
11
+ class LogStash::Inputs::GoogleCloudStorage < LogStash::Inputs::Base
12
+ config_name "google_cloud_storage"
13
+ default :codec, "plain"
14
+
15
+ config :project
16
+
17
+ # Path to JSON file containing the Service Account credentials (not needed when running inside GCE)
18
+ config :keyfile
19
+
20
+ # GCS private key password.
21
+ config :key_password, :validate => :string, :default => "notasecret"
22
+ #GCS service account
23
+ config :service_account, :validate => :string, :required => true
24
+
25
+ # The name of the GCS bucket.
26
+ config :bucket, :validate => :string, :required => true
27
+
28
+ # If specified, the prefix of filenames in the bucket must match (not a regexp)
29
+ config :prefix, :validate => :string, :default => nil
30
+
31
+ # Where to write the since database (keeps track of the date
32
+ # the last handled file was added to S3). The default will write
33
+ # sincedb files to some path matching "$HOME/.sincedb*"
34
+ # Should be a path with filename not just a directory.
35
+ config :sincedb_path, :validate => :string, :default => nil
36
+
37
+ # Name of a GCS bucket to backup processed files to.
38
+ config :backup_to_bucket, :validate => :string, :default => nil
39
+
40
+ # Append a prefix to the key (full path including file name in gcs) after processing.
41
+ # If backing up to another (or the same) bucket, this effectively lets you
42
+ # choose a new 'folder' to place the files in
43
+ config :backup_add_prefix, :validate => :string, :default => nil
44
+
45
+ # Path of a local directory to backup processed files to.
46
+ config :backup_to_dir, :validate => :string, :default => nil
47
+
48
+ # Whether to delete processed files from the original bucket.
49
+ config :delete, :validate => :boolean, :default => false
50
+
51
+ # Interval to wait between to check the file list again after a run is finished.
52
+ # Value is in seconds.
53
+ config :interval, :validate => :number, :default => 60
54
+
55
+ # Ruby style regexp of keys to exclude from the bucket
56
+ config :exclude_pattern, :validate => :string, :default => nil
57
+
58
+ # Set the directory where logstash will store the tmp files before processing them.
59
+ # default to the current OS temporary directory in linux /tmp/logstash
60
+ config :temporary_directory, :validate => :string, :default => File.join(Dir.tmpdir, "logstash")
61
+
62
+
63
+ public
64
+ def register
65
+ @host = Socket.gethostname
66
+
67
+ require "fileutils"
68
+ require "digest/md5"
69
+ require "google/api_client"
70
+ require "openssl"
71
+
72
+ @logger.debug("Registering GCS input", :bucket => @bucket, :project => @project, :keyfile => @keyfile)
73
+ # initialize_google_client
74
+ @logger.info ("\n===========================GCS INPUT PLUG-IN===========================")
75
+ @client = Google::APIClient.new(:application_name =>
76
+ 'Logstash Google Cloud Storage input plugin',
77
+ :application_version => '0.1')
78
+
79
+ key = Google::APIClient::PKCS12.load_key(@keyfile, @key_password)
80
+ service_account = Google::APIClient::JWTAsserter.new(@service_account,
81
+ 'https://www.googleapis.com/auth/devstorage.read_write',
82
+ key)
83
+ @client.authorization = service_account.authorize
84
+ @gcs = @client.discovered_api('storage', 'v1')
85
+
86
+
87
+ unless @backup_to_dir.nil?
88
+ Dir.mkdir(@backup_to_dir, 0700) unless File.exists?(@backup_to_dir)
89
+ end
90
+
91
+ FileUtils.mkdir_p(@temporary_directory) unless Dir.exist?(@temporary_directory)
92
+ end # def register
93
+
94
+ def run(queue)
95
+ @current_thread = Thread.current
96
+ Stud.interval(@interval) do
97
+ process_files(queue)
98
+ end
99
+ end # def run
100
+
101
+
102
+
103
+ public
104
+ def list_new_files
105
+
106
+
107
+ @logger.debug("GCS input: Polling new objects from bucket "+ @bucket)
108
+
109
+ objects = @client.execute(
110
+ api_method: @gcs.objects.list,
111
+ parameters: {bucket: @bucket}
112
+ )
113
+
114
+ logFiles = {}
115
+
116
+ objects.data.items.each do |file|
117
+
118
+ unless ignore_filename?(file.name)
119
+ if sincedb.newer?(file.updated)
120
+ logFiles[file.name] = file.updated
121
+ @logger.info("GCS input: Adding to objects[]", :name => file.name)
122
+ @logger.debug("GCS input: objects[] length is: ", :length => logFiles.length)
123
+ end
124
+ end
125
+
126
+ end
127
+
128
+
129
+ return logFiles.keys.sort {|a,b| logFiles[a] <=> logFiles[b]}
130
+ end # def fetch_new_files
131
+
132
+
133
+
134
+
135
+ public
136
+ def backup_to_bucket(filename)
137
+ unless @backup_to_bucket.nil?
138
+ backup_key = "#{@backup_add_prefix}#{filename}"
139
+
140
+ @logger.debug ("GCS input: bck_up object " + backup_key)
141
+
142
+ result = @client.execute(
143
+ api_method: @gcs.objects.copy,
144
+ parameters: {destinationBucket: @backup_to_bucket, destinationObject:backup_key, sourceBucket: @bucket, sourceObject: filename }
145
+ )
146
+
147
+ if @delete
148
+ result = @client.execute(
149
+ api_method: @gcs.objects.delete,
150
+ parameters: { bucket: @bucket, object: filename }
151
+ )
152
+ end
153
+ end
154
+ end
155
+
156
+ public
157
+ def backup_to_dir(filename)
158
+ unless @backup_to_dir.nil?
159
+ FileUtils.cp(filename, @backup_to_dir)
160
+ end
161
+ end
162
+
163
+
164
+ public
165
+ def process_files(queue)
166
+ objects = list_new_files
167
+
168
+ objects.each do |filename|
169
+ if stop?
170
+ break
171
+ else
172
+ @logger.debug("GCS input: processing ", :bucket => @bucket, :filename => filename)
173
+ process_log(queue, filename)
174
+ end
175
+ end
176
+ end # def process_files
177
+
178
+
179
+
180
+ public
181
+ def stop
182
+ # @current_thread is initialized in the `#run` method,
183
+ # this variable is needed because the `#stop` is a called in another thread
184
+ # than the `#run` method and requiring us to call stop! with a explicit thread.
185
+ Stud.stop!(@current_thread)
186
+ end
187
+
188
+
189
+ private
190
+
191
+ # Read the content of the local file
192
+ #
193
+ # @param [Queue] Where to push the event
194
+ # @param [String] Which file to read from
195
+ # @return [Boolean] True if the file was completely read, false otherwise.
196
+ def process_local_log(queue, filename, key)
197
+ @logger.debug('GCS input: processing file ', :filename => filename)
198
+ metadata = {}
199
+ # Currently codecs operates on bytes instead of stream.
200
+ # So all IO stuff: decompression, reading need to be done in the actual
201
+ # input and send as bytes to the codecs.
202
+ read_file(filename) do |line|
203
+ if stop?
204
+ @logger.warn("Logstash GCS input, stop reading in the middle of the file, we will read it again when logstash is started")
205
+ return false
206
+ end
207
+
208
+ @codec.decode(line) do |event|
209
+ # We are making an assumption concerning cloudfront
210
+ # log format, the user will use the plain or the line codec
211
+ # and the message key will represent the actual line content.
212
+ # If the event is only metadata the event will be drop.
213
+ # This was the behavior of the pre 1.5 plugin.
214
+ #
215
+ # The line need to go through the codecs to replace
216
+ # unknown bytes in the log stream before doing a regexp match or
217
+ # you will get a `Error: invalid byte sequence in UTF-8'
218
+ #if event_is_metadata?(event)
219
+ # @logger.debug('Event is metadata, updating the current cloudfront metadata', :event => event)
220
+ # update_metadata(metadata, event)
221
+ #else
222
+
223
+ event.set("[@metadata][gcs]", { "key" => key })
224
+ event.set("[@metadata][host]", @host)
225
+ decorate(event)
226
+ queue << event
227
+ ##end
228
+ end
229
+ end
230
+
231
+ return true
232
+ end # def process_local_log
233
+
234
+
235
+ private
236
+ def event_is_metadata?(event)
237
+ return false unless event.get("message").class == String
238
+ line = event.get("message")
239
+ version_metadata?(line) || fields_metadata?(line)
240
+ end
241
+
242
+ private
243
+ def version_metadata?(line)
244
+ line.start_with?('#Version: ')
245
+ end
246
+
247
+ private
248
+ def fields_metadata?(line)
249
+ line.start_with?('#Fields: ')
250
+ end
251
+
252
+ private
253
+ def update_metadata(metadata, event)
254
+ line = event.get('message').strip
255
+
256
+ if version_metadata?(line)
257
+ metadata[:cloudfront_version] = line.split(/#Version: (.+)/).last
258
+ end
259
+
260
+ if fields_metadata?(line)
261
+ metadata[:cloudfront_fields] = line.split(/#Fields: (.+)/).last
262
+ end
263
+ end
264
+
265
+ private
266
+ def read_file(filename, &block)
267
+ if gzip?(filename)
268
+ read_gzip_file(filename, block)
269
+ else
270
+ read_plain_file(filename, block)
271
+ end
272
+ end
273
+
274
+ def read_plain_file(filename, block)
275
+ File.open(filename, 'rb') do |file|
276
+ file.each(&block)
277
+ end
278
+ end
279
+
280
+ private
281
+ def read_gzip_file(filename, block)
282
+ # Details about multiple streams and the usage of unused from: http://code.activestate.com/lists/ruby-talk/11168/
283
+ File.open(filename) do |zio|
284
+ while true do
285
+ io = Zlib::GzipReader.new(zio)
286
+ io.each_line { |line| block.call(line) }
287
+ unused = io.unused
288
+ io.finish
289
+ break if unused.nil?
290
+ zio.pos -= unused.length # reset the position to the other block in the stream
291
+ end
292
+ end
293
+ rescue Zlib::Error, Zlib::GzipFile::Error => e
294
+ @logger.error("Gzip codec: We cannot uncompress the gzip file", :filename => filename)
295
+ raise e
296
+ end
297
+
298
+ private
299
+ def gzip?(filename)
300
+ filename.end_with?('.gz')
301
+ end
302
+
303
+ private
304
+ def sincedb
305
+ @sincedb ||= if @sincedb_path.nil?
306
+ @logger.debug("Using default generated file for the sincedb", :filename => sincedb_file)
307
+ SinceDB::File.new(sincedb_file)
308
+ else
309
+ @logger.debug("Using the provided sincedb_path",
310
+ :sincedb_path => @sincedb_path)
311
+ SinceDB::File.new(@sincedb_path)
312
+ end
313
+ end
314
+
315
+ private
316
+ def sincedb_file
317
+ File.join(ENV["HOME"], ".sincedb_" + Digest::MD5.hexdigest("#{@bucket}+#{@prefix}"))
318
+ end
319
+
320
+ private
321
+ def ignore_filename?(filename)
322
+ if @prefix == filename
323
+ return true
324
+ elsif filename.end_with?("/")
325
+ return true
326
+ elsif (@backup_add_prefix && @backup_to_bucket == @bucket && filename =~ /^#{backup_add_prefix}/)
327
+ return true
328
+ elsif @exclude_pattern.nil?
329
+ return false
330
+ elsif filename =~ Regexp.new(@exclude_pattern)
331
+ return true
332
+ else
333
+ return false
334
+ end
335
+ end
336
+
337
+ private
338
+ def process_log(queue, key)
339
+
340
+ object = @client.execute(
341
+ api_method: @gcs.objects.get,
342
+ parameters: {bucket: @bucket, object: key}
343
+ )
344
+
345
+ objectdata = @client.execute(
346
+ api_method: @gcs.objects.get,
347
+ parameters: {bucket: @bucket, object: key, alt: 'media'}
348
+ )
349
+
350
+
351
+ filename = File.join(temporary_directory, File.basename(key))
352
+
353
+ if download_remote_file(objectdata.body, filename)
354
+
355
+ if process_local_log(queue, filename, key)
356
+ lastmod = object.data['updated']
357
+ backup_to_bucket(key)
358
+ backup_to_dir(filename)
359
+ delete_file_from_bucket(key)
360
+ FileUtils.remove_entry_secure(filename, true)
361
+ sincedb.write(lastmod)
362
+
363
+ end
364
+ else
365
+ FileUtils.remove_entry_secure(filename, true)
366
+ end
367
+ end
368
+
369
+ private
370
+ # Stream the remove file to the local disk
371
+ #
372
+ # @param [GCS_OBJECT] Data from GCS object to download
373
+ # @param [String] The Temporary filename to stream to.
374
+ # @return [Boolean] True if the file was completely downloaded
375
+ def download_remote_file(remote_object, local_filename)
376
+ completed = false
377
+
378
+ ##TODO NEED CHANGE IN WRITE LOGIC TO AVOID MEMORY ISSUES
379
+
380
+ File.open(local_filename, 'wb') { |file| file.write(remote_object) }
381
+ completed = true
382
+
383
+ return completed
384
+ end
385
+
386
+ private
387
+ def delete_file_from_bucket(object)
388
+ if @delete and @backup_to_bucket.nil?
389
+ object.delete()
390
+ end
391
+ end
392
+
393
+
394
+
395
+ private
396
+ module SinceDB
397
+ class File
398
+ def initialize(file)
399
+ @sincedb_path = file
400
+ end
401
+
402
+ def newer?(date)
403
+ date.to_i > read.to_i
404
+ end
405
+
406
+ def read
407
+ if ::File.exists?(@sincedb_path)
408
+ content = ::File.read(@sincedb_path).chomp.strip
409
+ # If the file was created but we didn't have the time to write to it
410
+ return content.empty? ? Time.new(0) : Time.parse(content)
411
+ else
412
+ return Time.new(0)
413
+ end
414
+ end
415
+
416
+ def write(since = nil)
417
+ since = Time.now() if since.nil?
418
+ ::File.open(@sincedb_path, 'w') { |file| file.write(since.to_s) }
419
+ end
420
+ end
421
+ end
422
+ end # class LogStash::Inputs::GoogleCloudStorage
423
+
424
+
425
+ ### my other snippets :: jaspaul ::
426
+ # # List all buckets in the project
427
+ # bucket_list_result = @client.execute(
428
+ # api_method: @gcs.buckets.list,
429
+ # parameters: {project: @project}
430
+ # )
431
+ #
432
+ # @logger.info(" buckets body: " + bucket_list_result.body)
@@ -0,0 +1,28 @@
1
+
2
+ Gem::Specification.new do |s|
3
+ s.name = 'logstash-input-gcp_storage'
4
+ s.version = '0.1.0'
5
+ s.licenses = ['Apache License (2.0)']
6
+ s.summary = "plugin to read log events from Google Cloud Storage (GCS)"
7
+ s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
8
+ s.authors = ['Jaspaul Chahal','daniel']
9
+ s.email = 'jashchahal@gmail.com'
10
+ s.require_paths = ['lib']
11
+
12
+ # Files
13
+ s.files = Dir['lib/**/*','spec/**/*','vendor/**/*','*.gemspec','*.md','CONTRIBUTORS','Gemfile','LICENSE','NOTICE.TXT']
14
+ # Tests
15
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
16
+
17
+ # Special flag to let us know this is actually a logstash plugin
18
+ s.metadata = { "logstash_plugin" => "true", "logstash_group" => "input" }
19
+
20
+ # Gem dependencies
21
+ s.add_runtime_dependency "logstash-core-plugin-api", "~> 1.0"
22
+ s.add_runtime_dependency 'logstash-codec-plain'
23
+ s.add_runtime_dependency 'mime-types', '~> 2' # last version compatible with ruby 2.x
24
+
25
+ s.add_runtime_dependency 'stud'
26
+ # s.add_runtime_dependency 'google-cloud-storage'
27
+ s.add_runtime_dependency 'google-api-client', '~> 0.8.7' # version 0.9.x works only with ruby 2.x
28
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+ require "logstash/devutils/rspec/spec_helper"
3
+ require "logstash/inputs/google_cloud_storage"
4
+
5
+ describe LogStash::Inputs::GoogleCloudStorage do
6
+
7
+ let(:client) { double("google-client") }
8
+ let(:service_account) { double("service-account") }
9
+ let(:key) { "key" }
10
+
11
+ before(:each) do
12
+ allow(Google::APIClient).to receive(:new).and_return(client)
13
+ allow(client).to receive(:discovered_api).with("storage", "v1")
14
+ allow(Google::APIClient::PKCS12).to receive(:load_key).with("", "notasecret").and_return(key)
15
+ allow(Google::APIClient::JWTAsserter).to receive(:new).and_return(service_account)
16
+ allow(client).to receive(:authorization=)
17
+ allow(service_account).to receive(:authorize)
18
+ end
19
+
20
+
21
+ it "should register without errors" do
22
+ plugin = LogStash::Plugin.lookup("input", "google_cloud_storage").new({"bucket" => "", "key_path" => "", "service_account" => ""})
23
+ expect { plugin.register }.to_not raise_error
24
+ end
25
+
26
+ end
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logstash-input-gcp_storage
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jaspaul Chahal
8
+ - daniel
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2018-08-03 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ name: logstash-core-plugin-api
21
+ prerelease: false
22
+ type: :runtime
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.0'
28
+ - !ruby/object:Gem::Dependency
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ name: logstash-codec-plain
35
+ prerelease: false
36
+ type: :runtime
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2'
48
+ name: mime-types
49
+ prerelease: false
50
+ type: :runtime
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '2'
56
+ - !ruby/object:Gem::Dependency
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ name: stud
63
+ prerelease: false
64
+ type: :runtime
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.8.7
76
+ name: google-api-client
77
+ prerelease: false
78
+ type: :runtime
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: 0.8.7
84
+ description: This gem is a Logstash plugin required to be installed on top of the
85
+ Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This
86
+ gem is not a stand-alone program
87
+ email: jashchahal@gmail.com
88
+ executables: []
89
+ extensions: []
90
+ extra_rdoc_files: []
91
+ files:
92
+ - CHANGELOG.md
93
+ - CONTRIBUTORS
94
+ - DEVELOPER.md
95
+ - Gemfile
96
+ - LICENSE
97
+ - README.md
98
+ - lib/logstash/inputs/google_cloud_storage.rb
99
+ - logstash-input-google_cloud_storage.gemspec
100
+ - spec/inputs/google_cloud_storage_spec.rb
101
+ homepage:
102
+ licenses:
103
+ - Apache License (2.0)
104
+ metadata:
105
+ logstash_plugin: 'true'
106
+ logstash_group: input
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 2.6.13
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: plugin to read log events from Google Cloud Storage (GCS)
127
+ test_files:
128
+ - spec/inputs/google_cloud_storage_spec.rb