logstash-output-azureblob 0.9.0

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.
@@ -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