logstash-output-azure 0.3.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|