logstash-output-azure 0.3.0 → 1.0.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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +4 -1
- data/CONTRIBUTORS +1 -0
- data/lib/logstash/outputs/azure.rb +59 -81
- data/lib/logstash/outputs/blob/file_repository.rb +33 -18
- data/lib/logstash/outputs/blob/path_validator.rb +3 -3
- data/lib/logstash/outputs/blob/size_and_time_rotation_policy.rb +6 -4
- data/lib/logstash/outputs/blob/size_rotation_policy.rb +5 -4
- data/lib/logstash/outputs/blob/temporary_file.rb +28 -19
- data/lib/logstash/outputs/blob/temporary_file_factory.rb +28 -16
- data/lib/logstash/outputs/blob/time_rotation_policy.rb +5 -4
- data/lib/logstash/outputs/blob/uploader.rb +29 -22
- data/lib/logstash/outputs/blob/writable_directory_validator.rb +6 -7
- data/logstash-output-azure.gemspec +10 -10
- data/spec/outputs/azure_spec.rb +16 -18
- data/spec/outputs/blob/file_repository_spec.rb +35 -38
- data/spec/outputs/blob/size_and_time_rotation_policy_spec.rb +20 -21
- data/spec/outputs/blob/size_rotation_policy_spec.rb +13 -15
- data/spec/outputs/blob/temporary_file_factory_spec.rb +27 -28
- data/spec/outputs/blob/temporary_file_spec.rb +14 -15
- data/spec/outputs/blob/time_rotation_policy_spec.rb +17 -18
- data/spec/outputs/blob/uploader_spec.rb +28 -32
- data/spec/outputs/blob/writable_directory_validator_spec.rb +8 -9
- data/spec/spec_helper.rb +4 -5
- data/spec/supports/helpers.rb +12 -15
- metadata +9 -9
@@ -1,16 +1,15 @@
|
|
1
|
-
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require "securerandom"
|
1
|
+
require 'logstash/devutils/rspec/spec_helper'
|
2
|
+
require 'logstash/outputs/blob/temporary_file'
|
3
|
+
require 'stud/temporary'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'securerandom'
|
7
6
|
|
8
7
|
describe LogStash::Outputs::LogstashAzureBlobOutput::TemporaryFile do
|
9
|
-
let(:content) {
|
10
|
-
let(:key) {
|
8
|
+
let(:content) { 'hello world' }
|
9
|
+
let(:key) { 'foo' }
|
11
10
|
let(:uuid) { SecureRandom.uuid }
|
12
|
-
let(:temporary_file) { ::File.open(::File.join(temporary_directory, uuid, key),
|
13
|
-
let(:temporary_directory) {
|
11
|
+
let(:temporary_file) { ::File.open(::File.join(temporary_directory, uuid, key), 'w+') }
|
12
|
+
let(:temporary_directory) { Stud::Temporary.directory }
|
14
13
|
|
15
14
|
before :each do
|
16
15
|
FileUtils.mkdir_p(::File.join(temporary_directory, uuid))
|
@@ -18,30 +17,30 @@ describe LogStash::Outputs::LogstashAzureBlobOutput::TemporaryFile do
|
|
18
17
|
|
19
18
|
subject { described_class.new(key, temporary_file, temporary_directory) }
|
20
19
|
|
21
|
-
it
|
20
|
+
it 'returns the key of the file' do
|
22
21
|
expect(subject.key).to eq(key)
|
23
22
|
end
|
24
23
|
|
25
|
-
it
|
24
|
+
it 'saves content to a file' do
|
26
25
|
subject.write(content)
|
27
26
|
subject.close
|
28
27
|
expect(File.read(subject.path).strip).to eq(content)
|
29
28
|
end
|
30
29
|
|
31
|
-
it
|
30
|
+
it 'deletes a file' do
|
32
31
|
expect(File.exist?(subject.path)).to be_truthy
|
33
32
|
subject.delete!
|
34
33
|
expect(File.exist?(subject.path)).to be_falsey
|
35
34
|
end
|
36
35
|
|
37
|
-
it
|
36
|
+
it 'successfully delete a file already closed' do
|
38
37
|
subject.close
|
39
38
|
expect(File.exist?(subject.path)).to be_truthy
|
40
39
|
subject.delete!
|
41
40
|
expect(File.exist?(subject.path)).to be_falsey
|
42
41
|
end
|
43
42
|
|
44
|
-
it
|
43
|
+
it 'returns the creation time' do
|
45
44
|
expect(subject.ctime).to be < Time.now + 0.5
|
46
45
|
end
|
47
46
|
end
|
@@ -1,60 +1,59 @@
|
|
1
|
-
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require "logstash/outputs/blob/temporary_file"
|
1
|
+
require 'logstash/devutils/rspec/spec_helper'
|
2
|
+
require 'logstash/outputs/blob/time_rotation_policy'
|
3
|
+
require 'logstash/outputs/blob/temporary_file'
|
5
4
|
|
6
5
|
describe LogStash::Outputs::LogstashAzureBlobOutput::TimeRotationPolicy do
|
7
6
|
subject { described_class.new(max_time) }
|
8
7
|
|
9
8
|
let(:max_time) { 1 }
|
10
|
-
let(:temporary_directory) {
|
9
|
+
let(:temporary_directory) { Stud::Temporary.directory }
|
11
10
|
let(:temporary_file) { Stud::Temporary.file }
|
12
|
-
let(:name) {
|
13
|
-
let(:content) {
|
11
|
+
let(:name) { 'foobar' }
|
12
|
+
let(:content) { 'hello' * 1000 }
|
14
13
|
let(:file) { LogStash::Outputs::LogstashAzureBlobOutput::TemporaryFile.new(name, temporary_file, temporary_directory) }
|
15
14
|
|
16
|
-
it
|
15
|
+
it 'raises an exception if the `file_time` is set to 0' do
|
17
16
|
expect { described_class.new(0) }.to raise_error(LogStash::ConfigurationError, /`time_file` need to be greather than 0/)
|
18
17
|
end
|
19
18
|
|
20
|
-
it
|
19
|
+
it 'raises an exception if the `file_time` is < 0' do
|
21
20
|
expect { described_class.new(-100) }.to raise_error(LogStash::ConfigurationError, /`time_file` need to be greather than 0/)
|
22
21
|
end
|
23
22
|
|
24
|
-
context
|
23
|
+
context 'when the size of the file is superior to 0' do
|
25
24
|
before :each do
|
26
25
|
file.write(content)
|
27
26
|
file.fsync
|
28
27
|
end
|
29
28
|
|
30
|
-
it
|
29
|
+
it 'returns true if the file old enough' do
|
31
30
|
allow(file).to receive(:ctime).and_return(Time.now - (max_time * 2 * 60))
|
32
31
|
expect(subject.rotate?(file)).to be_truthy
|
33
32
|
end
|
34
33
|
|
35
|
-
it
|
34
|
+
it 'returns false is not old enough' do
|
36
35
|
expect(subject.rotate?(file)).to be_falsey
|
37
36
|
end
|
38
37
|
end
|
39
38
|
|
40
|
-
context
|
41
|
-
it
|
39
|
+
context 'When the size of the file is 0' do
|
40
|
+
it 'returns false if the file old enough' do
|
42
41
|
allow(file).to receive(:ctime).and_return(Time.now - (max_time * 2 * 60))
|
43
42
|
expect(subject.rotate?(file)).to be_falsey
|
44
43
|
end
|
45
44
|
|
46
|
-
it
|
45
|
+
it 'returns false is not old enough' do
|
47
46
|
expect(subject.rotate?(file)).to be_falsey
|
48
47
|
end
|
49
48
|
end
|
50
49
|
|
51
|
-
context
|
52
|
-
it
|
50
|
+
context '#needs_periodic?' do
|
51
|
+
it 'return false' do
|
53
52
|
expect(subject.needs_periodic?).to be_truthy
|
54
53
|
end
|
55
54
|
end
|
56
55
|
|
57
|
-
it
|
56
|
+
it 'convert minute into seconds' do
|
58
57
|
expect(subject.time_file).to eq(60)
|
59
58
|
end
|
60
59
|
end
|
@@ -1,65 +1,61 @@
|
|
1
|
-
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require "stud/temporary"
|
1
|
+
require 'logstash/devutils/rspec/spec_helper'
|
2
|
+
require 'logstash/outputs/blob/uploader'
|
3
|
+
require 'logstash/outputs/blob/temporary_file'
|
4
|
+
require 'azure'
|
5
|
+
require 'stud/temporary'
|
7
6
|
|
8
7
|
describe LogStash::Outputs::LogstashAzureBlobOutput::Uploader do
|
9
|
-
let(:logger) { spy(:logger
|
8
|
+
let(:logger) { spy(:logger) }
|
10
9
|
let(:max_upload_workers) { 1 }
|
11
|
-
let(:storage_account_name) {
|
10
|
+
let(:storage_account_name) { 'test-cointainer' }
|
12
11
|
let(:temporary_directory) { Stud::Temporary.pathname }
|
13
12
|
let(:temporary_file) { Stud::Temporary.file }
|
14
|
-
let(:storage_access_key) {
|
13
|
+
let(:storage_access_key) { 'foobar' }
|
15
14
|
let(:upload_options) { {} }
|
16
15
|
let(:threadpool) do
|
17
|
-
Concurrent::ThreadPoolExecutor.new(
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
:fallback_policy => :caller_runs
|
22
|
-
})
|
16
|
+
Concurrent::ThreadPoolExecutor.new(min_threads: 1,
|
17
|
+
max_threads: 8,
|
18
|
+
max_queue: 1,
|
19
|
+
fallback_policy: :caller_runs)
|
23
20
|
end
|
24
21
|
|
25
22
|
let(:file) do
|
26
23
|
f = LogStash::Outputs::LogstashAzureBlobOutput::TemporaryFile.new(storage_access_key, temporary_file, temporary_directory)
|
27
|
-
f.write(
|
24
|
+
f.write('random content')
|
28
25
|
f.fsync
|
29
26
|
f
|
30
27
|
end
|
31
28
|
|
32
|
-
#subject { described_class.new(storage_account_name, logger, threadpool) }
|
29
|
+
# subject { described_class.new(storage_account_name, logger, threadpool) }
|
33
30
|
|
34
|
-
#it "upload file to the blob" do
|
31
|
+
# it "upload file to the blob" do
|
35
32
|
# expect { subject.upload(file) }.not_to raise_error
|
36
|
-
#end
|
33
|
+
# end
|
37
34
|
|
38
|
-
#it "execute a callback when the upload is complete" do
|
35
|
+
# it "execute a callback when the upload is complete" do
|
39
36
|
# callback = proc { |f| }
|
40
37
|
|
41
38
|
# expect(callback).to receive(:call).with(file)
|
42
39
|
# subject.upload(file, { :on_complete => callback })
|
43
|
-
#end
|
40
|
+
# end
|
44
41
|
|
45
|
-
#it 'the content in the blob and sent should be equal' do
|
42
|
+
# it 'the content in the blob and sent should be equal' do
|
46
43
|
# blob = subject.upload(file)
|
47
44
|
# md5 = Digest::MD5.base64digest(Object::File.open(file.path).read)
|
48
45
|
# expect(blob.properties[:content_md5]).to eq(md5)
|
49
|
-
#end
|
46
|
+
# end
|
50
47
|
|
51
|
-
# xit "retries errors indefinitively" do
|
52
|
-
# blob = double("blob").as_null_object
|
48
|
+
# xit "retries errors indefinitively" do
|
49
|
+
# blob = double("blob").as_null_object
|
53
50
|
|
54
|
-
# expect(logger).to receive(:error).with(any_args).once
|
51
|
+
# expect(logger).to receive(:error).with(any_args).once
|
55
52
|
|
56
|
-
# expect(storage_account_name).to receive(:object).with(file.key).and_return(blob).twice
|
53
|
+
# expect(storage_account_name).to receive(:object).with(file.key).and_return(blob).twice
|
57
54
|
|
58
|
-
# expect(blob).to receive(:upload_file).with(any_args).and_raise(StandardError)
|
55
|
+
# expect(blob).to receive(:upload_file).with(any_args).and_raise(StandardError)
|
59
56
|
|
60
|
-
# expect(blob).to receive(:upload_file).with(any_args).and_return(true)
|
57
|
+
# expect(blob).to receive(:upload_file).with(any_args).and_return(true)
|
61
58
|
|
62
|
-
|
63
|
-
#
|
64
|
-
# end
|
59
|
+
# subject.upload(file)
|
60
|
+
# end
|
65
61
|
end
|
@@ -1,22 +1,21 @@
|
|
1
|
-
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require "stud/temporary"
|
1
|
+
require 'logstash/devutils/rspec/spec_helper'
|
2
|
+
require 'logstash/outputs/blob/writable_directory_validator'
|
3
|
+
require 'stud/temporary'
|
5
4
|
|
6
5
|
describe LogStash::Outputs::LogstashAzureBlobOutput::WritableDirectoryValidator do
|
7
|
-
let(:temporary_directory) {
|
6
|
+
let(:temporary_directory) { File.join(Stud::Temporary.directory, Time.now.to_i.to_s) }
|
8
7
|
|
9
8
|
subject { described_class }
|
10
9
|
|
11
10
|
context "when the directory doesn't exists" do
|
12
|
-
it
|
11
|
+
it 'creates the directory' do
|
13
12
|
expect(Dir.exist?(temporary_directory)).to be_falsey
|
14
13
|
expect(subject.valid?(temporary_directory)).to be_truthy
|
15
14
|
expect(Dir.exist?(temporary_directory)).to be_truthy
|
16
15
|
end
|
17
16
|
end
|
18
17
|
|
19
|
-
context
|
18
|
+
context 'when the directory exist' do
|
20
19
|
before do
|
21
20
|
FileUtils.mkdir_p(temporary_directory)
|
22
21
|
end
|
@@ -28,12 +27,12 @@ describe LogStash::Outputs::LogstashAzureBlobOutput::WritableDirectoryValidator
|
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
31
|
-
it
|
30
|
+
it 'return false if the directory is not writable' do
|
32
31
|
expect(::File).to receive(:writable?).with(temporary_directory).and_return(false)
|
33
32
|
expect(subject.valid?(temporary_directory)).to be_falsey
|
34
33
|
end
|
35
34
|
|
36
|
-
it
|
35
|
+
it 'return true if the directory is writable' do
|
37
36
|
expect(::File).to receive(:writable?).with(temporary_directory).and_return(true)
|
38
37
|
expect(subject.valid?(temporary_directory)).to be_truthy
|
39
38
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
require "logstash/logging/logger"
|
1
|
+
require 'logstash/devutils/rspec/spec_helper'
|
2
|
+
require_relative 'supports/helpers'
|
3
|
+
require 'logstash/logging/logger'
|
5
4
|
|
6
|
-
LogStash::Logging::Logger
|
5
|
+
LogStash::Logging::Logger.configure_logging('debug') if ENV['DEBUG']
|
data/spec/supports/helpers.rb
CHANGED
@@ -1,30 +1,27 @@
|
|
1
|
-
|
2
|
-
shared_context "setup plugin" do
|
1
|
+
shared_context 'setup plugin' do
|
3
2
|
let(:temporary_directory) { Stud::Temporary.pathname }
|
4
3
|
let(:storage_account_name) { ENV['AZURE_STORAGE_ACCOUNT'] }
|
5
|
-
let(:storage_access_key) {
|
4
|
+
let(:storage_access_key) { ENV['AZURE_STORAGE_ACCESS_KEY'] }
|
6
5
|
let(:size_file) { 100 }
|
7
6
|
let(:time_file) { 100 }
|
8
7
|
let(:tags) { [] }
|
9
|
-
let(:prefix) {
|
8
|
+
let(:prefix) { 'home' }
|
10
9
|
|
11
10
|
let(:main_options) do
|
12
11
|
{
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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' => []
|
20
19
|
}
|
21
20
|
end
|
22
21
|
|
23
22
|
subject { LogStash::Outputs::LogstashAzureBlobOutput.new(options) }
|
24
23
|
end
|
25
24
|
|
26
|
-
def clean_remote_files(prefix =
|
27
|
-
bucket_resource.objects(:
|
28
|
-
object.delete
|
29
|
-
end
|
25
|
+
def clean_remote_files(prefix = '')
|
26
|
+
bucket_resource.objects(prefix: prefix).each(&:delete)
|
30
27
|
end
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-output-azure
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tuffk
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: azure
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0.7'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0.7'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: logstash-codec-plain
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -39,19 +39,19 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: logstash-core-plugin-api
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0
|
47
|
+
version: '2.0'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0
|
54
|
+
version: '2.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: logstash-devutils
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
122
|
version: '0'
|
123
123
|
requirements: []
|
124
124
|
rubyforge_project:
|
125
|
-
rubygems_version: 2.
|
125
|
+
rubygems_version: 2.7.2
|
126
126
|
signing_key:
|
127
127
|
specification_version: 4
|
128
128
|
summary: Plugin for logstash to send output to Microsoft Azure Blob
|