logstash-output-azureblob 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,46 @@
1
+ require 'logstash/devutils/rspec/spec_helper'
2
+ require 'logstash/outputs/blob/temporary_file'
3
+ require 'stud/temporary'
4
+ require 'fileutils'
5
+ require 'securerandom'
6
+
7
+ describe LogStash::Outputs::LogstashAzureBlobOutput::TemporaryFile do
8
+ let(:content) { 'hello world' }
9
+ let(:key) { 'foo' }
10
+ let(:uuid) { SecureRandom.uuid }
11
+ let(:temporary_file) { ::File.open(::File.join(temporary_directory, uuid, key), 'w+') }
12
+ let(:temporary_directory) { Stud::Temporary.directory }
13
+
14
+ before :each do
15
+ FileUtils.mkdir_p(::File.join(temporary_directory, uuid))
16
+ end
17
+
18
+ subject { described_class.new(key, temporary_file, temporary_directory) }
19
+
20
+ it 'returns the key of the file' do
21
+ expect(subject.key).to eq(key)
22
+ end
23
+
24
+ it 'saves content to a file' do
25
+ subject.write(content)
26
+ subject.close
27
+ expect(File.read(subject.path).strip).to eq(content)
28
+ end
29
+
30
+ it 'deletes a file' do
31
+ expect(File.exist?(subject.path)).to be_truthy
32
+ subject.delete!
33
+ expect(File.exist?(subject.path)).to be_falsey
34
+ end
35
+
36
+ it 'successfully delete a file already closed' do
37
+ subject.close
38
+ expect(File.exist?(subject.path)).to be_truthy
39
+ subject.delete!
40
+ expect(File.exist?(subject.path)).to be_falsey
41
+ end
42
+
43
+ it 'returns the creation time' do
44
+ expect(subject.ctime).to be < Time.now + 0.5
45
+ end
46
+ end
@@ -0,0 +1,59 @@
1
+ require 'logstash/devutils/rspec/spec_helper'
2
+ require 'logstash/outputs/blob/time_rotation_policy'
3
+ require 'logstash/outputs/blob/temporary_file'
4
+
5
+ describe LogStash::Outputs::LogstashAzureBlobOutput::TimeRotationPolicy do
6
+ subject { described_class.new(max_time) }
7
+
8
+ let(:max_time) { 1 }
9
+ let(:temporary_directory) { Stud::Temporary.directory }
10
+ let(:temporary_file) { Stud::Temporary.file }
11
+ let(:name) { 'foobar' }
12
+ let(:content) { 'hello' * 1000 }
13
+ let(:file) { LogStash::Outputs::LogstashAzureBlobOutput::TemporaryFile.new(name, temporary_file, temporary_directory) }
14
+
15
+ it 'raises an exception if the `file_time` is set to 0' do
16
+ expect { described_class.new(0) }.to raise_error(LogStash::ConfigurationError, /`time_file` need to be greather than 0/)
17
+ end
18
+
19
+ it 'raises an exception if the `file_time` is < 0' do
20
+ expect { described_class.new(-100) }.to raise_error(LogStash::ConfigurationError, /`time_file` need to be greather than 0/)
21
+ end
22
+
23
+ context 'when the size of the file is superior to 0' do
24
+ before :each do
25
+ file.write(content)
26
+ file.fsync
27
+ end
28
+
29
+ it 'returns true if the file old enough' do
30
+ allow(file).to receive(:ctime).and_return(Time.now - (max_time * 2 * 60))
31
+ expect(subject.rotate?(file)).to be_truthy
32
+ end
33
+
34
+ it 'returns false is not old enough' do
35
+ expect(subject.rotate?(file)).to be_falsey
36
+ end
37
+ end
38
+
39
+ context 'When the size of the file is 0' do
40
+ it 'returns false if the file old enough' do
41
+ allow(file).to receive(:ctime).and_return(Time.now - (max_time * 2 * 60))
42
+ expect(subject.rotate?(file)).to be_falsey
43
+ end
44
+
45
+ it 'returns false is not old enough' do
46
+ expect(subject.rotate?(file)).to be_falsey
47
+ end
48
+ end
49
+
50
+ context '#needs_periodic?' do
51
+ it 'return false' do
52
+ expect(subject.needs_periodic?).to be_truthy
53
+ end
54
+ end
55
+
56
+ it 'convert minute into seconds' do
57
+ expect(subject.time_file).to eq(60)
58
+ end
59
+ end
@@ -0,0 +1,61 @@
1
+ require 'logstash/devutils/rspec/spec_helper'
2
+ require 'logstash/outputs/blob/uploader'
3
+ require 'logstash/outputs/blob/temporary_file'
4
+ require 'azure/storage/common'
5
+ require 'azure/storage/blob'
6
+ require 'stud/temporary'
7
+
8
+ describe LogStash::Outputs::LogstashAzureBlobOutput::Uploader do
9
+ let(:logger) { spy(:logger) }
10
+ let(:max_upload_workers) { 1 }
11
+ let(:storage_account_name) { 'test-cointainer' }
12
+ let(:temporary_directory) { Stud::Temporary.pathname }
13
+ let(:temporary_file) { Stud::Temporary.file }
14
+ let(:storage_access_key) { 'foobar' }
15
+ let(:threadpool) do
16
+ Concurrent::ThreadPoolExecutor.new(min_threads: 1,
17
+ max_threads: 8,
18
+ max_queue: 1,
19
+ fallback_policy: :caller_runs)
20
+ end
21
+
22
+ let(:file) do
23
+ f = LogStash::Outputs::LogstashAzureBlobOutput::TemporaryFile.new(storage_access_key, temporary_file, temporary_directory)
24
+ f.write('random content')
25
+ f.fsync
26
+ f
27
+ end
28
+
29
+ # subject { described_class.new(storage_account_name, logger, threadpool) }
30
+
31
+ # it "upload file to the blob" do
32
+ # expect { subject.upload(file) }.not_to raise_error
33
+ # end
34
+
35
+ # it "execute a callback when the upload is complete" do
36
+ # callback = proc { |f| }
37
+
38
+ # expect(callback).to receive(:call).with(file)
39
+ # subject.upload(file, { :on_complete => callback })
40
+ # end
41
+
42
+ # it 'the content in the blob and sent should be equal' do
43
+ # blob = subject.upload(file)
44
+ # md5 = Digest::MD5.base64digest(Object::File.open(file.path).read)
45
+ # expect(blob.properties[:content_md5]).to eq(md5)
46
+ # end
47
+
48
+ # xit "retries errors indefinitively" do
49
+ # blob = double("blob").as_null_object
50
+
51
+ # expect(logger).to receive(:error).with(any_args).once
52
+
53
+ # expect(storage_account_name).to receive(:object).with(file.key).and_return(blob).twice
54
+
55
+ # expect(blob).to receive(:upload_file).with(any_args).and_raise(StandardError)
56
+
57
+ # expect(blob).to receive(:upload_file).with(any_args).and_return(true)
58
+
59
+ # subject.upload(file)
60
+ # end
61
+ end
@@ -0,0 +1,39 @@
1
+ require 'logstash/devutils/rspec/spec_helper'
2
+ require 'logstash/outputs/blob/writable_directory_validator'
3
+ require 'stud/temporary'
4
+
5
+ describe LogStash::Outputs::LogstashAzureBlobOutput::WritableDirectoryValidator do
6
+ let(:temporary_directory) { File.join(Stud::Temporary.directory, Time.now.to_i.to_s) }
7
+
8
+ subject { described_class }
9
+
10
+ context "when the directory doesn't exists" do
11
+ it 'creates the directory' do
12
+ expect(Dir.exist?(temporary_directory)).to be_falsey
13
+ expect(subject.valid?(temporary_directory)).to be_truthy
14
+ expect(Dir.exist?(temporary_directory)).to be_truthy
15
+ end
16
+ end
17
+
18
+ context 'when the directory exist' do
19
+ before do
20
+ FileUtils.mkdir_p(temporary_directory)
21
+ end
22
+
23
+ it "doesn't change the directory" do
24
+ expect(Dir.exist?(temporary_directory)).to be_truthy
25
+ expect(subject.valid?(temporary_directory)).to be_truthy
26
+ expect(Dir.exist?(temporary_directory)).to be_truthy
27
+ end
28
+ end
29
+
30
+ it 'return false if the directory is not writable' do
31
+ expect(::File).to receive(:writable?).with(temporary_directory).and_return(false)
32
+ expect(subject.valid?(temporary_directory)).to be_falsey
33
+ end
34
+
35
+ it 'return true if the directory is writable' do
36
+ expect(::File).to receive(:writable?).with(temporary_directory).and_return(true)
37
+ expect(subject.valid?(temporary_directory)).to be_truthy
38
+ end
39
+ end
@@ -0,0 +1,5 @@
1
+ require 'logstash/devutils/rspec/spec_helper'
2
+ require_relative 'supports/helpers'
3
+ require 'logstash/logging/logger'
4
+
5
+ LogStash::Logging::Logger.configure_logging('debug') if ENV['DEBUG']
@@ -0,0 +1,27 @@
1
+ shared_context 'setup plugin' do
2
+ let(:temporary_directory) { Stud::Temporary.pathname }
3
+ let(:storage_account_name) { ENV['AZURE_STORAGE_ACCOUNT'] }
4
+ let(:storage_access_key) { ENV['AZURE_STORAGE_ACCESS_KEY'] }
5
+ let(:size_file) { 100 }
6
+ let(:time_file) { 100 }
7
+ let(:tags) { [] }
8
+ let(:prefix) { 'home' }
9
+
10
+ let(:main_options) do
11
+ {
12
+ 'storage_account_name' => bucket,
13
+ 'prefix' => prefix,
14
+ 'temporary_directory' => temporary_directory,
15
+ 'storage_access_key' => access_key_id,
16
+ 'size_file' => size_file,
17
+ 'time_file' => time_file,
18
+ 'tags' => []
19
+ }
20
+ end
21
+
22
+ subject { LogStash::Outputs::LogstashAzureBlobOutput.new(options) }
23
+ end
24
+
25
+ def clean_remote_files(prefix = '')
26
+ bucket_resource.objects(prefix: prefix).each(&:delete)
27
+ end
metadata ADDED
@@ -0,0 +1,141 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logstash-output-azureblob
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ platform: ruby
6
+ authors:
7
+ - Sean Stark
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-02-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '2.0'
19
+ name: azure-storage-blob
20
+ prerelease: false
21
+ type: :runtime
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ name: logstash-codec-plain
34
+ prerelease: false
35
+ type: :runtime
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '2.1'
47
+ name: logstash-core-plugin-api
48
+ prerelease: false
49
+ type: :runtime
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.1'
55
+ - !ruby/object:Gem::Dependency
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ name: logstash-devutils
62
+ prerelease: false
63
+ type: :development
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: This output plugin will send logs to azure blob storage. This does not
70
+ support ADLS2 endpoints
71
+ email: sean.stark@microsoft.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - CHANGELOG.md
77
+ - CONTRIBUTORS
78
+ - DEVELOPER.md
79
+ - Gemfile
80
+ - LICENSE
81
+ - README.md
82
+ - lib/logstash/outputs/azure_blob.rb
83
+ - lib/logstash/outputs/blob/file_repository.rb
84
+ - lib/logstash/outputs/blob/path_validator.rb
85
+ - lib/logstash/outputs/blob/size_and_time_rotation_policy.rb
86
+ - lib/logstash/outputs/blob/size_rotation_policy.rb
87
+ - lib/logstash/outputs/blob/temporary_file.rb
88
+ - lib/logstash/outputs/blob/temporary_file_factory.rb
89
+ - lib/logstash/outputs/blob/time_rotation_policy.rb
90
+ - lib/logstash/outputs/blob/uploader.rb
91
+ - lib/logstash/outputs/blob/writable_directory_validator.rb
92
+ - lib/logstash/outputs/template.rb
93
+ - logstash-output-azureblob.gemspec
94
+ - spec/outputs/azureblob_spec.rb
95
+ - spec/outputs/blob/file_repository_spec.rb
96
+ - spec/outputs/blob/size_and_time_rotation_policy_spec.rb
97
+ - spec/outputs/blob/size_rotation_policy_spec.rb
98
+ - spec/outputs/blob/temporary_file_factory_spec.rb
99
+ - spec/outputs/blob/temporary_file_spec.rb
100
+ - spec/outputs/blob/time_rotation_policy_spec.rb
101
+ - spec/outputs/blob/uploader_spec.rb
102
+ - spec/outputs/blob/writable_directory_validator_spec.rb
103
+ - spec/spec_helper.rb
104
+ - spec/supports/helpers.rb
105
+ homepage: https://github.com/seanstark/logstash-output-azureblob
106
+ licenses:
107
+ - Apache License (2.0)
108
+ metadata:
109
+ logstash_plugin: 'true'
110
+ logstash_group: output
111
+ post_install_message:
112
+ rdoc_options: []
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ requirements: []
126
+ rubygems_version: 3.2.3
127
+ signing_key:
128
+ specification_version: 4
129
+ summary: Output plugin for logstash to send output to Azure Blob Storage
130
+ test_files:
131
+ - spec/outputs/azureblob_spec.rb
132
+ - spec/outputs/blob/file_repository_spec.rb
133
+ - spec/outputs/blob/size_and_time_rotation_policy_spec.rb
134
+ - spec/outputs/blob/size_rotation_policy_spec.rb
135
+ - spec/outputs/blob/temporary_file_factory_spec.rb
136
+ - spec/outputs/blob/temporary_file_spec.rb
137
+ - spec/outputs/blob/time_rotation_policy_spec.rb
138
+ - spec/outputs/blob/uploader_spec.rb
139
+ - spec/outputs/blob/writable_directory_validator_spec.rb
140
+ - spec/spec_helper.rb
141
+ - spec/supports/helpers.rb