logstash-input-google_cloud_storage 0.9.0-java

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.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +9 -0
  3. data/CONTRIBUTING.md +7 -0
  4. data/CONTRIBUTORS +11 -0
  5. data/Gemfile +10 -0
  6. data/LICENSE +11 -0
  7. data/README.md +95 -0
  8. data/docs/configuration.asciidoc +112 -0
  9. data/docs/examples.asciidoc +84 -0
  10. data/docs/index.asciidoc +43 -0
  11. data/docs/metadata.asciidoc +20 -0
  12. data/docs/resources.asciidoc +6 -0
  13. data/lib/logstash-input-google_cloud_storage_jars.rb +38 -0
  14. data/lib/logstash/inputs/cloud_storage/blob_adapter.rb +92 -0
  15. data/lib/logstash/inputs/cloud_storage/blob_filter.rb +99 -0
  16. data/lib/logstash/inputs/cloud_storage/client.rb +87 -0
  17. data/lib/logstash/inputs/cloud_storage/file_reader.rb +59 -0
  18. data/lib/logstash/inputs/cloud_storage/processed_db.rb +53 -0
  19. data/lib/logstash/inputs/google_cloud_storage.rb +130 -0
  20. data/logstash-input-google_cloud_storage.gemspec +49 -0
  21. data/spec/fixtures/credentials.json +8 -0
  22. data/spec/fixtures/helloworld.log +2 -0
  23. data/spec/fixtures/helloworld.log.gz +0 -0
  24. data/spec/inputs/cloud_storage/blob_adapter_spec.rb +95 -0
  25. data/spec/inputs/cloud_storage/blob_filter_spec.rb +92 -0
  26. data/spec/inputs/cloud_storage/client_spec.rb +33 -0
  27. data/spec/inputs/cloud_storage/file_reader_spec.rb +76 -0
  28. data/spec/inputs/cloud_storage/processed_db_spec.rb +82 -0
  29. data/spec/inputs/google_cloud_storage_spec.rb +127 -0
  30. data/vendor/jar-dependencies/com/fasterxml/jackson/core/jackson-core/2.1.3/jackson-core-2.1.3.jar +0 -0
  31. data/vendor/jar-dependencies/com/google/api-client/google-api-client/1.23.0/google-api-client-1.23.0.jar +0 -0
  32. data/vendor/jar-dependencies/com/google/api/api-common/1.5.0/api-common-1.5.0.jar +0 -0
  33. data/vendor/jar-dependencies/com/google/api/gax-httpjson/0.40.0/gax-httpjson-0.40.0.jar +0 -0
  34. data/vendor/jar-dependencies/com/google/api/gax/1.23.0/gax-1.23.0.jar +0 -0
  35. data/vendor/jar-dependencies/com/google/api/grpc/proto-google-common-protos/1.7.0/proto-google-common-protos-1.7.0.jar +0 -0
  36. data/vendor/jar-dependencies/com/google/api/grpc/proto-google-iam-v1/0.8.0/proto-google-iam-v1-0.8.0.jar +0 -0
  37. data/vendor/jar-dependencies/com/google/apis/google-api-services-storage/v1-rev114-1.23.0/google-api-services-storage-v1-rev114-1.23.0.jar +0 -0
  38. data/vendor/jar-dependencies/com/google/auth/google-auth-library-credentials/0.9.0/google-auth-library-credentials-0.9.0.jar +0 -0
  39. data/vendor/jar-dependencies/com/google/auth/google-auth-library-oauth2-http/0.9.0/google-auth-library-oauth2-http-0.9.0.jar +0 -0
  40. data/vendor/jar-dependencies/com/google/cloud/google-cloud-core-http/1.25.0/google-cloud-core-http-1.25.0.jar +0 -0
  41. data/vendor/jar-dependencies/com/google/cloud/google-cloud-core/1.25.0/google-cloud-core-1.25.0.jar +0 -0
  42. data/vendor/jar-dependencies/com/google/cloud/google-cloud-storage/1.25.0/google-cloud-storage-1.25.0.jar +0 -0
  43. data/vendor/jar-dependencies/com/google/code/findbugs/jsr305/3.0.1/jsr305-3.0.1.jar +0 -0
  44. data/vendor/jar-dependencies/com/google/code/gson/gson/2.7/gson-2.7.jar +0 -0
  45. data/vendor/jar-dependencies/com/google/errorprone/error_prone_annotations/2.2.0/error_prone_annotations-2.2.0.jar +0 -0
  46. data/vendor/jar-dependencies/com/google/guava/guava-jdk5/17.0/guava-jdk5-17.0.jar +0 -0
  47. data/vendor/jar-dependencies/com/google/guava/guava/20.0/guava-20.0.jar +0 -0
  48. data/vendor/jar-dependencies/com/google/http-client/google-http-client-appengine/1.23.0/google-http-client-appengine-1.23.0.jar +0 -0
  49. data/vendor/jar-dependencies/com/google/http-client/google-http-client-jackson/1.23.0/google-http-client-jackson-1.23.0.jar +0 -0
  50. data/vendor/jar-dependencies/com/google/http-client/google-http-client-jackson2/1.23.0/google-http-client-jackson2-1.23.0.jar +0 -0
  51. data/vendor/jar-dependencies/com/google/http-client/google-http-client/1.23.0/google-http-client-1.23.0.jar +0 -0
  52. data/vendor/jar-dependencies/com/google/oauth-client/google-oauth-client/1.23.0/google-oauth-client-1.23.0.jar +0 -0
  53. data/vendor/jar-dependencies/com/google/protobuf/protobuf-java-util/3.5.1/protobuf-java-util-3.5.1.jar +0 -0
  54. data/vendor/jar-dependencies/com/google/protobuf/protobuf-java/3.5.1/protobuf-java-3.5.1.jar +0 -0
  55. data/vendor/jar-dependencies/commons-codec/commons-codec/1.3/commons-codec-1.3.jar +0 -0
  56. data/vendor/jar-dependencies/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar +0 -0
  57. data/vendor/jar-dependencies/io/grpc/grpc-context/1.9.0/grpc-context-1.9.0.jar +0 -0
  58. data/vendor/jar-dependencies/io/opencensus/opencensus-api/0.11.1/opencensus-api-0.11.1.jar +0 -0
  59. data/vendor/jar-dependencies/io/opencensus/opencensus-contrib-http-util/0.11.1/opencensus-contrib-http-util-0.11.1.jar +0 -0
  60. data/vendor/jar-dependencies/joda-time/joda-time/2.9.2/joda-time-2.9.2.jar +0 -0
  61. data/vendor/jar-dependencies/org/apache/httpcomponents/httpclient/4.0.1/httpclient-4.0.1.jar +0 -0
  62. data/vendor/jar-dependencies/org/apache/httpcomponents/httpcore/4.0.1/httpcore-4.0.1.jar +0 -0
  63. data/vendor/jar-dependencies/org/codehaus/jackson/jackson-core-asl/1.9.11/jackson-core-asl-1.9.11.jar +0 -0
  64. data/vendor/jar-dependencies/org/threeten/threetenbp/1.3.3/threetenbp-1.3.3.jar +0 -0
  65. metadata +191 -0
@@ -0,0 +1,49 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'logstash-input-google_cloud_storage'
3
+ s.version = '0.9.0'
4
+ s.licenses = ['Apache-2.0']
5
+ s.summary = 'Plugin to import log data from Google Cloud Storage (GCS).'
6
+ s.description = 'This gem is a Logstash plugin required to be installed on top of the '\
7
+ 'Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. '\
8
+ 'This gem is not a stand-alone program'
9
+ s.homepage = 'http://www.elastic.co/guide/en/logstash/current/index.html'
10
+ s.authors = ['Elastic', 'Joseph Lewis III']
11
+ s.email = 'info@elastic.co'
12
+ s.require_paths = ['lib', 'vendor/jar-dependencies']
13
+
14
+ # Files
15
+ s.files = Dir[
16
+ # Code
17
+ 'lib/**/*',
18
+ 'spec/**/*',
19
+ 'vendor/**/*',
20
+ 'vendor/jar-dependencies/**/*.jar',
21
+ 'vendor/jar-dependencies/**/*.rb',
22
+ # Library
23
+ 'Gemfile',
24
+ '*.gemspec',
25
+ # Documentation
26
+ '*.md',
27
+ 'CONTRIBUTORS',
28
+ 'LICENSE',
29
+ 'NOTICE.TXT',
30
+ 'VERSION',
31
+ 'docs/**/*']
32
+
33
+ # Tests
34
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
35
+
36
+ # Special flag to let us know this is actually a logstash plugin
37
+ s.metadata = { 'logstash_plugin' => 'true', 'logstash_group' => 'input' }
38
+
39
+ # Gem dependencies
40
+ s.add_runtime_dependency 'logstash-codec-plain'
41
+ s.add_runtime_dependency 'logstash-core-plugin-api', '~> 2.0'
42
+ s.add_runtime_dependency 'stud', '>= 0.0.22'
43
+
44
+ s.add_development_dependency 'logstash-devutils', '>= 0.0.16'
45
+
46
+ # Java
47
+ s.add_development_dependency 'jar-dependencies', '~> 0.3.4'
48
+ s.platform = 'java'
49
+ end
@@ -0,0 +1,8 @@
1
+ {
2
+ "//": "Dummy account from https://github.com/GoogleCloudPlatform/google-cloud-java/google-cloud-clients/google-cloud-core/src/test/java/com/google/cloud/ServiceOptionsTest.java",
3
+ "private_key_id": "somekeyid",
4
+ "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC+K2hSuFpAdrJI\nnCgcDz2M7t7bjdlsadsasad+fvRSW6TjNQZ3p5LLQY1kSZRqBqylRkzteMOyHgaR\n0Pmxh3ILCND5men43j3h4eDbrhQBuxfEMalkG92sL+PNQSETY2tnvXryOvmBRwa/\nQP/9dJfIkIDJ9Fw9N4Bhhhp6mCcRpdQjV38H7JsyJ7lih/oNjECgYAt\nknddadwkwewcVxHFhcZJO+XWf6ofLUXpRwiTZakGMn8EE1uVa2LgczOjwWHGi99MFjxSer5m9\n1tCa3/KEGKiS/YL71JvjwX3mb+cewlkcmweBKZHM2JPTk0ZednFSpVZMtycjkbLa\ndYOS8V85AgMBewECggEBAKksaldajfDZDV6nGqbFjMiizAKJolr/M3OQw16K6o3/\n0S31xIe3sSlgW0+UbYlF4U8KifhManD1apVSC3csafaspP4RZUHFhtBywLO9pR5c\nr6S5aLp+gPWFyIp1pfXbWGvc5VY/v9x7ya1VEa6rXvLsKupSeWAW4tMj3eo/64ge\nsdaceaLYw52KeBYiT6+vpsnYrEkAHO1fF/LavbLLOFJmFTMxmsNaG0tuiJHgjshB\n82DpMCbXG9YcCgI/DbzuIjsdj2JC1cascSP//3PmefWysucBQe7Jryb6NQtASmnv\nCdDw/0jmZTEjpe4S1lxfHplAhHFtdgYTvyYtaLZiVVkCgYEA8eVpof2rceecw/I6\n5ng1q3Hl2usdWV/4mZMvR0fOemacLLfocX6IYxT1zA1FFJlbXSRsJMf/Qq39mOR2\nSpW+hr4jCoHeRVYLgsbggtrevGmILAlNoqCMpGZ6vDmJpq6ECV9olliDvpPgWOP+\nmYPDreFBGxWvQrADNbRt2dmGsrsCgYEAyUHqB2wvJHFqdmeBsaacewzV8x9WgmeX\ngUIi9REwXlGDW0Mz50dxpxcKCAYn65+7TCnY5O/jmL0VRxU1J2mSWyWTo1C+17L0\n3fUqjxL1pkefwecxwecvC+gFFYdJ4CQ/MHHXU81Lwl1iWdFCd2UoGddYaOF+KNeM\nHC7cmqra+JsCgYEAlUNywzq8nUg7282E+uICfCB0LfwejuymR93CtsFgb7cRd6ak\nECR8FGfCpH8ruWJINllbQfcHVCX47ndLZwqv3oVFKh6pAS/vVI4dpOepP8++7y1u\ncoOvtreXCX6XqfrWDtKIvv0vjlHBhhhp6mCcRpdQjV38H7JsyJ7lih/oNjECgYAt\nkndj5uNl5SiuVxHFhcZJO+XWf6ofLUregtevZakGMn8EE1uVa2AY7eafmoU/nZPT\n00YB0TBATdCbn/nBSuKDESkhSg9s2GEKQZG5hBmL5uCMfo09z3SfxZIhJdlerreP\nJ7gSidI12N+EZxYd4xIJh/HFDgp7RRO87f+WJkofMQKBgGTnClK1VMaCRbJZPriw\nEfeFCoOX75MxKwXs6xgrw4W//AYGGUjDt83lD6AZP6tws7gJ2IwY/qP7+lyhjEqN\nHtfPZRGFkGZsdaksdlaksd323423d+15/UvrlRSFPNj1tWQmNKkXyRDW4IG1Oa2p\nrALStNBx5Y9t0/LQnFI4w3aG\n-----END PRIVATE KEY-----\n",
5
+ "client_email": "someclientid@developer.gserviceaccount.com",
6
+ "client_id": "someclientid.apps.googleusercontent.com",
7
+ "type": "service_account"
8
+ }
@@ -0,0 +1,2 @@
1
+ hello
2
+ world
@@ -0,0 +1,95 @@
1
+ # encoding: utf-8
2
+
3
+ # Copyright 2018 Google LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'logstash/devutils/rspec/spec_helper'
18
+ require 'logstash/inputs/google_cloud_storage'
19
+ require 'logstash/inputs/cloud_storage/blob_adapter'
20
+
21
+ describe LogStash::Inputs::CloudStorage::BlobAdapter do
22
+ let(:blob) do
23
+ double('Blob',
24
+ :getBucket => 'bucket',
25
+ :getMetadata => {},
26
+ :getName => 'name',
27
+ :getMd5 => 'md5',
28
+ :getCrc32c => 'crc',
29
+ :getGeneration => 123,
30
+ :downloadTo => true)
31
+ end
32
+ subject { LogStash::Inputs::CloudStorage::BlobAdapter.new(blob) }
33
+
34
+ describe '#attributes' do
35
+ it 'includes the bucket ID as bucket' do
36
+ expect(subject.attributes).to have_key('bucket')
37
+ end
38
+
39
+ it 'includes metadata as metadata' do
40
+ expect(subject.attributes).to have_key('metadata')
41
+ end
42
+
43
+ it 'includes the blob name as name' do
44
+ expect(subject.attributes).to have_key('name')
45
+ end
46
+
47
+ it 'includes the md5 as md5' do
48
+ expect(subject.attributes).to have_key('md5')
49
+ end
50
+
51
+ it 'includes the crc32c as crc32c' do
52
+ expect(subject.attributes).to have_key('crc32c')
53
+ end
54
+
55
+ it 'includes the generation as generation' do
56
+ expect(subject.attributes).to have_key('generation')
57
+ end
58
+ end
59
+
60
+ describe '#line_attributes' do
61
+ it 'sets line_id to the correct format' do
62
+ attrs = subject.line_attributes(9876)
63
+ expect(attrs['line_id']).to eq('gs://bucket/name:9876@123')
64
+ end
65
+
66
+ it 'includes line' do
67
+ attrs = subject.line_attributes(9876)
68
+ expect(attrs['line']).to eq(9876)
69
+ end
70
+ end
71
+
72
+ describe '#with_downloaded' do
73
+ before(:each) do
74
+ allow(FileUtils).to receive(:remove_entry_secure)
75
+ end
76
+
77
+ it 'uses temp_directory as a base' do
78
+ expect { |b| subject.with_downloaded('foo', &b) }.to yield_with_args(/foo.*/)
79
+ end
80
+
81
+ it 'calls downloadTo on the blob' do
82
+ expect(blob).to receive(:downloadTo)
83
+ subject.with_downloaded('foo') {}
84
+ end
85
+
86
+ it 'yields the downloaded file' do
87
+ expect { |b| subject.with_downloaded('foo', &b) }.to yield_with_args(String)
88
+ end
89
+
90
+ it 'securely deletes the file once done' do
91
+ expect(FileUtils).to receive(:remove_entry_secure)
92
+ subject.with_downloaded('foo') {}
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,92 @@
1
+ # encoding: utf-8
2
+
3
+ # Copyright 2018 Google LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'logstash/devutils/rspec/spec_helper'
18
+ require 'logstash/inputs/google_cloud_storage'
19
+ require 'logstash/inputs/cloud_storage/blob_filter'
20
+ require 'logstash/inputs/cloud_storage/blob_adapter'
21
+
22
+ describe LogStash::Inputs::CloudStorage::BlobFilter do
23
+ describe '#initialize' do
24
+ it 'should fail with invalid match regex' do
25
+ expect { make_filter(:include_regex => '(') }.to raise_error(RuntimeError)
26
+ end
27
+
28
+ it 'should fail with invalid exclude regex' do
29
+ expect { make_filter(:exclude_regex => '(') }.to raise_error(RuntimeError)
30
+ end
31
+ end
32
+
33
+ describe '#should_process?' do
34
+ let(:java_blob) do
35
+ double('Blob',
36
+ :getBucket => 'bucket',
37
+ :getMetadata => { 'some-tag' => 'true' },
38
+ :getName => 'path/to/log.log.gz',
39
+ :getMd5 => 'md5',
40
+ :getCrc32c => 'crc',
41
+ :getGeneration => 123,
42
+ :downloadTo => true)
43
+ end
44
+ let(:blob) { LogStash::Inputs::CloudStorage::BlobAdapter.new(java_blob) }
45
+ let(:passdb) { double('passdb', :already_processed? => false) }
46
+ let(:faildb) { double('passdb', :already_processed? => true) }
47
+
48
+ it 'should be able to pass with a blob that meets all conditions' do
49
+ subject = make_filter
50
+
51
+ expect(subject.should_process?(blob)).to eq(true)
52
+ end
53
+
54
+ it 'should fail if a blob is in the processed database' do
55
+ subject = make_filter(:processed_db => faildb)
56
+
57
+ expect(subject.should_process?(blob)).to eq(false)
58
+ end
59
+
60
+ it 'should fail if a blob does not match the include regex' do
61
+ subject = make_filter(:include_regex => '.*.json')
62
+
63
+ expect(subject.should_process?(blob)).to eq(false)
64
+ end
65
+
66
+ it 'should fail if a blob matches the exclude regex' do
67
+ subject = make_filter(:exclude_regex => '.*')
68
+
69
+ expect(subject.should_process?(blob)).to eq(false)
70
+
71
+ end
72
+
73
+ it 'should fail if it has an already processed metadata tag' do
74
+ subject = make_filter(:metadata_key => 'some-tag')
75
+
76
+ expect(subject.should_process?(blob)).to eq(false)
77
+
78
+ end
79
+ end
80
+
81
+ def make_filter(options = {})
82
+ logger = spy('logger')
83
+
84
+ LogStash::Inputs::CloudStorage::BlobFilter.new(
85
+ logger,
86
+ options[:include_regex] || '.*',
87
+ options[:exclude_regex] || '^$',
88
+ options[:metadata_key] || '',
89
+ options[:processed_db] || nil
90
+ )
91
+ end
92
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+
3
+ # Copyright 2018 Google LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'logstash/devutils/rspec/spec_helper'
18
+ require 'logstash/inputs/google_cloud_storage'
19
+ require 'logstash/inputs/cloud_storage/client'
20
+
21
+ describe LogStash::Inputs::CloudStorage::Client do
22
+
23
+ # This test is mostly to make sure the Java types, signatures and classes
24
+ # haven't changed being that JRuby is very relaxed.
25
+ describe '#initialize' do
26
+ let(:logger) { spy('logger') }
27
+
28
+ it 'does not throw an error when initializing' do
29
+ key_file = ::File.join('spec', 'fixtures', 'credentials.json')
30
+ LogStash::Inputs::CloudStorage::Client.new('my-bucket', key_file, logger)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,76 @@
1
+ # encoding: utf-8
2
+
3
+ # Copyright 2018 Google LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'logstash/devutils/rspec/spec_helper'
18
+ require 'logstash/inputs/google_cloud_storage'
19
+ require 'logstash/inputs/cloud_storage/file_reader'
20
+
21
+ describe LogStash::Inputs::CloudStorage::FileReader do
22
+ describe '#gzip?' do
23
+ GzipTest = Struct.new('GzipTest', :path, :expected)
24
+
25
+ it 'is true when the file ends with .gz' do
26
+ cases = [
27
+ GzipTest.new('simple.gz', true),
28
+ GzipTest.new('subdir/simple.gz', true),
29
+ GzipTest.new('/abs/path.gz', true),
30
+ GzipTest.new('path.log.gz', true),
31
+
32
+ GzipTest.new('path.log.gzip', false),
33
+ GzipTest.new('simple.log', false),
34
+ GzipTest.new('simple.gz/foo', false),
35
+ GzipTest.new('simple.gz.log', false),
36
+ GzipTest.new('foo.tgz', false)
37
+ ]
38
+
39
+ cases.each do |test|
40
+ result = LogStash::Inputs::CloudStorage::FileReader.gzip?(test.path)
41
+
42
+ expect(result).to eq(test.expected)
43
+ end
44
+ end
45
+ end
46
+
47
+ describe '#read_plain_lines' do
48
+ let(:path) { ::File.join('spec', 'fixtures', 'helloworld.log') }
49
+
50
+ it 'reads plain files' do
51
+ expected = [['hello', 1], ['world', 2]]
52
+
53
+ out = []
54
+ LogStash::Inputs::CloudStorage::FileReader.read_plain_lines(path) do |text, linenum|
55
+ out << [text, linenum]
56
+ end
57
+
58
+ expect(out).to eq(expected)
59
+ end
60
+ end
61
+
62
+ describe '#read_gzip_lines' do
63
+ let(:path) { ::File.join('spec', 'fixtures', 'helloworld.log.gz') }
64
+
65
+ it 'reads gzipped files' do
66
+ expected = [['hello', 1], ['world', 2]]
67
+
68
+ out = []
69
+ LogStash::Inputs::CloudStorage::FileReader.read_gzip_lines(path) do |text, linenum|
70
+ out << [text, linenum]
71
+ end
72
+
73
+ expect(out).to eq(expected)
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,82 @@
1
+ # encoding: utf-8
2
+
3
+ # Copyright 2018 Google LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'logstash/devutils/rspec/spec_helper'
18
+ require 'logstash/inputs/google_cloud_storage'
19
+ require 'logstash/inputs/cloud_storage/processed_db'
20
+
21
+ describe LogStash::Inputs::CloudStorage::ProcessedDb do
22
+
23
+ let(:blob) { double('blob', :name => 'foo', :generation => 12_345) }
24
+ subject { LogStash::Inputs::CloudStorage::ProcessedDb.new('base') }
25
+
26
+ describe '#encode_path' do
27
+ it 'includes the generation in the hash' do
28
+ blob2 = double('blob2', :name => 'foo', :generation => 54_321)
29
+
30
+ expect(subject.encode_path(blob)).to_not eq(subject.encode_path(blob2))
31
+ end
32
+
33
+ it 'includes the path in the hash' do
34
+ blob2 = double('blob2', :name => 'bar', :generation => 12_345)
35
+
36
+ expect(subject.encode_path(blob)).to_not eq(subject.encode_path(blob2))
37
+ end
38
+
39
+ it 'includes the base directory in the path' do
40
+ path = subject.encode_path(blob)
41
+
42
+ expect(path.start_with?('base')).to eq(true)
43
+ end
44
+
45
+ it 'splits the path into base/3/rest' do
46
+ path = subject.encode_path(blob)
47
+ parts = path.split(::File::SEPARATOR)
48
+
49
+ expect(parts.length).to eq(3)
50
+ expect(parts[0]).to eq('base')
51
+ expect(parts[1].length).to eq(3)
52
+ end
53
+
54
+ it 'produces a correct SHA1 path' do
55
+ expected = ::File.join('base', 'd27', '628eefc02ae87401aea8c57c49579fbd6b55e')
56
+
57
+ expect(subject.encode_path(blob)).to eq(expected)
58
+ end
59
+ end
60
+
61
+ # The tight coupling of the tests to already_processed? and mark_processed
62
+ # is intentional.
63
+ # It's critical the implementation remains the same between versions
64
+ # so upgrading the plugin version won't trigger a full re-index of a bucket.
65
+
66
+ describe '#already_processed?' do
67
+ it 'checks if the path returned from encode_path exists' do
68
+ allow(subject).to receive(:encode_path).and_return('path/to/create')
69
+ expect(::File).to receive(:exist?).with('path/to/create')
70
+
71
+ subject.already_processed?(blob)
72
+ end
73
+ end
74
+
75
+ describe '#mark_processed' do
76
+ it 'creates the directory and parent dirs for encode_path' do
77
+ allow(subject).to receive(:encode_path).and_return('path/to/create')
78
+
79
+ subject.already_processed?(blob)
80
+ end
81
+ end
82
+ end