s3_rotate 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.
@@ -0,0 +1,145 @@
1
+ # standard
2
+ require 'date'
3
+
4
+ # 3rd part
5
+ require 'fog-aws'
6
+
7
+ # s3_rotate
8
+ require File.expand_path("../../../../lib/s3_rotate/core/backup_uploader", __FILE__)
9
+ require File.expand_path("../../../../lib/s3_rotate/utils/file_utils", __FILE__)
10
+
11
+ describe S3Rotate::BackupUploader do
12
+
13
+ before :each do
14
+ @client = S3Rotate::S3Client.new('key', 'secret', 'bucket', 'region')
15
+ @uploader = S3Rotate::BackupUploader.new(@client)
16
+ end
17
+
18
+ describe '#initialize' do
19
+
20
+ it 'sets the client' do
21
+ expect(@uploader.s3_client).not_to eq nil
22
+ end
23
+
24
+ end
25
+
26
+ describe '#upload' do
27
+
28
+ it 'uploads all the new files until reaching an already uploaded file' do
29
+ # mock
30
+ @client.connection.directories.get('bucket').files.create(key: '/backup_name/daily/2020-01-02.tgz', body: 'some data')
31
+ @client.connection.directories.get('bucket').files.create(key: '/backup_name/daily/2020-01-03.tgz', body: 'some data')
32
+ @client.connection.directories.get('bucket').files.create(key: '/backup_name/daily/2020-01-04.tgz', body: 'some data')
33
+ @client.connection.directories.get('bucket').files.create(key: '/backup_name/weekly/2020-01-05.tgz', body: 'some data')
34
+ @client.connection.directories.get('bucket').files.create(key: '/backup_name/monthly/2020-01-06.tgz', body: 'some data')
35
+ @client.connection.directories.get('bucket').files.create(key: '/other_backup_name/daily/2020-01-07.tgz', body: 'some data')
36
+
37
+ allow(S3Rotate::FileUtils).to receive(:date_from_filename).and_call_original
38
+ allow(S3Rotate::FileUtils).to receive(:extension_from_filename).and_call_original
39
+ allow(S3Rotate::FileUtils).to receive(:files_in_directory).with('/path/to/dir').and_return([
40
+ 'some-backup-2020-01-01.tgz',
41
+ 'some-backup-2020-01-02.tgz',
42
+ 'some-backup-2020-01-03.tgz',
43
+ 'some-backup-2020-01-04.tgz',
44
+ 'some-backup-2020-01-05.tgz',
45
+ 'some-backup-2020-01-06.tgz',
46
+ 'some-backup-2020-01-07.tgz'
47
+ ])
48
+ allow(@client).to receive(:upload_local_backup_to_s3).and_return nil
49
+ allow(File).to receive(:open).and_return "raw_data"
50
+
51
+ # perform test
52
+ @uploader.upload('backup_name', '/path/to/dir')
53
+
54
+ # verify result
55
+ expect(@client).to have_received(:upload_local_backup_to_s3).exactly(3)
56
+ expect(@client).to have_received(:upload_local_backup_to_s3).with('backup_name', Date.new(2020, 1, 7), 'daily', '.tgz', 'raw_data')
57
+ expect(@client).to have_received(:upload_local_backup_to_s3).with('backup_name', Date.new(2020, 1, 6), 'daily', '.tgz', 'raw_data')
58
+ expect(@client).to have_received(:upload_local_backup_to_s3).with('backup_name', Date.new(2020, 1, 5), 'daily', '.tgz', 'raw_data')
59
+
60
+ expect(S3Rotate::FileUtils).to have_received(:date_from_filename).exactly(4)
61
+ expect(S3Rotate::FileUtils).to have_received(:date_from_filename).with('some-backup-2020-01-07.tgz', /\d{4}-\d{2}-\d{2}/)
62
+ expect(S3Rotate::FileUtils).to have_received(:date_from_filename).with('some-backup-2020-01-06.tgz', /\d{4}-\d{2}-\d{2}/)
63
+ expect(S3Rotate::FileUtils).to have_received(:date_from_filename).with('some-backup-2020-01-05.tgz', /\d{4}-\d{2}-\d{2}/)
64
+ expect(S3Rotate::FileUtils).to have_received(:date_from_filename).with('some-backup-2020-01-04.tgz', /\d{4}-\d{2}-\d{2}/)
65
+
66
+ expect(S3Rotate::FileUtils).to have_received(:extension_from_filename).exactly(4)
67
+ expect(S3Rotate::FileUtils).to have_received(:extension_from_filename).with('some-backup-2020-01-07.tgz')
68
+ expect(S3Rotate::FileUtils).to have_received(:extension_from_filename).with('some-backup-2020-01-06.tgz')
69
+ expect(S3Rotate::FileUtils).to have_received(:extension_from_filename).with('some-backup-2020-01-05.tgz')
70
+ expect(S3Rotate::FileUtils).to have_received(:extension_from_filename).with('some-backup-2020-01-04.tgz')
71
+ end
72
+
73
+ it 'uploads files without extensions' do
74
+ # mock
75
+ allow(S3Rotate::FileUtils).to receive(:date_from_filename).and_call_original
76
+ allow(S3Rotate::FileUtils).to receive(:extension_from_filename).and_return nil
77
+ allow(S3Rotate::FileUtils).to receive(:files_in_directory).with('/path/to/dir').and_return([
78
+ 'some-backup-2020-01-01.tgz',
79
+ 'some-backup-2020-01-02.tgz',
80
+ 'some-backup-2020-01-03.tgz',
81
+ ])
82
+ allow(@client).to receive(:upload_local_backup_to_s3).and_return nil
83
+ allow(File).to receive(:open).and_return "raw_data"
84
+
85
+ # perform test
86
+ @uploader.upload('backup_name', '/path/to/dir')
87
+
88
+ # verify result
89
+ expect(@client).to have_received(:upload_local_backup_to_s3).exactly(3)
90
+ expect(@client).to have_received(:upload_local_backup_to_s3).with('backup_name', Date.new(2020, 1, 3), 'daily', nil, 'raw_data')
91
+ expect(@client).to have_received(:upload_local_backup_to_s3).with('backup_name', Date.new(2020, 1, 2), 'daily', nil, 'raw_data')
92
+ expect(@client).to have_received(:upload_local_backup_to_s3).with('backup_name', Date.new(2020, 1, 1), 'daily', nil, 'raw_data')
93
+
94
+ expect(S3Rotate::FileUtils).to have_received(:date_from_filename).exactly(3)
95
+ expect(S3Rotate::FileUtils).to have_received(:date_from_filename).with('some-backup-2020-01-03.tgz', /\d{4}-\d{2}-\d{2}/)
96
+ expect(S3Rotate::FileUtils).to have_received(:date_from_filename).with('some-backup-2020-01-02.tgz', /\d{4}-\d{2}-\d{2}/)
97
+ expect(S3Rotate::FileUtils).to have_received(:date_from_filename).with('some-backup-2020-01-01.tgz', /\d{4}-\d{2}-\d{2}/)
98
+
99
+ expect(S3Rotate::FileUtils).to have_received(:extension_from_filename).exactly(3)
100
+ expect(S3Rotate::FileUtils).to have_received(:extension_from_filename).with('some-backup-2020-01-03.tgz')
101
+ expect(S3Rotate::FileUtils).to have_received(:extension_from_filename).with('some-backup-2020-01-02.tgz')
102
+ expect(S3Rotate::FileUtils).to have_received(:extension_from_filename).with('some-backup-2020-01-01.tgz')
103
+ end
104
+
105
+ it 'does not upload files with broken date' do
106
+ # mock
107
+ original_date_from_filename = S3Rotate::FileUtils.method(:date_from_filename)
108
+ allow(S3Rotate::FileUtils).to receive(:date_from_filename) do |filename, date_regex|
109
+ if filename == 'some-backup-2020-01-02.tgz'
110
+ nil
111
+ else
112
+ original_date_from_filename.call(filename, date_regex)
113
+ end
114
+ end
115
+ allow(S3Rotate::FileUtils).to receive(:extension_from_filename).and_call_original
116
+ allow(S3Rotate::FileUtils).to receive(:files_in_directory).with('/path/to/dir').and_return([
117
+ 'some-backup-2020-01-01.tgz',
118
+ 'some-backup-2020-01-02.tgz',
119
+ 'some-backup-2020-01-03.tgz',
120
+ ])
121
+ allow(@client).to receive(:upload_local_backup_to_s3).and_return nil
122
+ allow(File).to receive(:open).and_return "raw_data"
123
+
124
+ # perform test
125
+ @uploader.upload('backup_name', '/path/to/dir')
126
+
127
+ # verify result
128
+ expect(@client).to have_received(:upload_local_backup_to_s3).exactly(2)
129
+ expect(@client).to have_received(:upload_local_backup_to_s3).with('backup_name', Date.new(2020, 1, 3), 'daily', '.tgz', 'raw_data')
130
+ expect(@client).to have_received(:upload_local_backup_to_s3).with('backup_name', Date.new(2020, 1, 1), 'daily', '.tgz', 'raw_data')
131
+
132
+ expect(S3Rotate::FileUtils).to have_received(:date_from_filename).exactly(3)
133
+ expect(S3Rotate::FileUtils).to have_received(:date_from_filename).with('some-backup-2020-01-03.tgz', /\d{4}-\d{2}-\d{2}/)
134
+ expect(S3Rotate::FileUtils).to have_received(:date_from_filename).with('some-backup-2020-01-02.tgz', /\d{4}-\d{2}-\d{2}/)
135
+ expect(S3Rotate::FileUtils).to have_received(:date_from_filename).with('some-backup-2020-01-01.tgz', /\d{4}-\d{2}-\d{2}/)
136
+
137
+ expect(S3Rotate::FileUtils).to have_received(:extension_from_filename).exactly(3)
138
+ expect(S3Rotate::FileUtils).to have_received(:extension_from_filename).with('some-backup-2020-01-03.tgz')
139
+ expect(S3Rotate::FileUtils).to have_received(:extension_from_filename).with('some-backup-2020-01-02.tgz')
140
+ expect(S3Rotate::FileUtils).to have_received(:extension_from_filename).with('some-backup-2020-01-01.tgz')
141
+ end
142
+
143
+ end
144
+
145
+ end
@@ -0,0 +1,61 @@
1
+ # standard
2
+ require 'date'
3
+
4
+ # s3_rotate
5
+ require File.expand_path("../../../../lib/s3_rotate/utils/file_utils", __FILE__)
6
+
7
+ describe S3Rotate::FileUtils do
8
+
9
+ describe '#date_from_filename' do
10
+
11
+ it 'parses Date.parse formats' do
12
+ expect(S3Rotate::FileUtils::date_from_filename("/path/to/file-2020-12-13-backup.tar.gz")).to eq Date.new(2020, 12, 13)
13
+ end
14
+
15
+ it 'parses timestamp formats' do
16
+ expect(S3Rotate::FileUtils::date_from_filename("/path/to/file-1580098737-backup.tar.gz", /file-(\d+)-backup.tar.gz/)).to eq Date.new(2020, 1, 27)
17
+ end
18
+
19
+ it 'raises if the regex matched nothing' do
20
+ expect{ S3Rotate::FileUtils::date_from_filename("/path/to/file-1580098737-backup.tar.gz") }.to raise_error(RuntimeError, "Invalid date_regex or filename format")
21
+ end
22
+
23
+ it 'raises if the regex matched nothing' do
24
+ expect{ S3Rotate::FileUtils::date_from_filename("/path/to/file-1580098737-backup.tar.gz", /file-\d+-backup.tar.gz/) }.to raise_error(RuntimeError, "Date format not supported")
25
+ end
26
+
27
+ end
28
+
29
+ describe '#extension_from_filename' do
30
+
31
+ it 'handles no extension' do
32
+ expect(S3Rotate::FileUtils::extension_from_filename("backup")).to eq nil
33
+ end
34
+
35
+ it 'handles short extension' do
36
+ expect(S3Rotate::FileUtils::extension_from_filename("backup.tgz")).to eq '.tgz'
37
+ end
38
+
39
+ it 'handles long extension' do
40
+ expect(S3Rotate::FileUtils::extension_from_filename("backup.tar.gz.1")).to eq '.tar.gz.1'
41
+ end
42
+
43
+ it 'handles absolute paths' do
44
+ expect(S3Rotate::FileUtils::extension_from_filename("/path/to.file/backup.tar.gz.1")).to eq '.tar.gz.1'
45
+ end
46
+
47
+ end
48
+
49
+ describe 'files_in_directory' do
50
+
51
+ it 'returns the directory files ordered ASC' do
52
+ expect(S3Rotate::FileUtils::files_in_directory("#{__dir__}/mock")).to eq [ "backup-2020-01-02.test", "backup-2020-01-03.test", "backup-2020-02-01.test", "backup-2021-01-01.test" ]
53
+ end
54
+
55
+ it 'raises for invalid directories' do
56
+ expect{ S3Rotate::FileUtils::files_in_directory("/invalid/path") }.to raise_error(RuntimeError, "Invalid directory /invalid/path")
57
+ end
58
+
59
+ end
60
+
61
+ end
@@ -0,0 +1,15 @@
1
+ RSpec.configure do |c|
2
+
3
+ c.before :each do
4
+ Fog.mock!
5
+
6
+ fog = Fog::Storage.new(aws_access_key_id: 'key', aws_secret_access_key: 'secret', provider: 'AWS', region: 'region')
7
+ fog.directories.create(key: 'bucket')
8
+ end
9
+
10
+ c.after :each do
11
+ Fog::Mock.reset
12
+ Fog.unmock!
13
+ end
14
+
15
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: s3_rotate
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Simon Ninon
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-01-27 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: AWS S3 upload with rotation mechanism
14
+ email: simon.ninon@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - ".gitignore"
20
+ - ".rspec"
21
+ - Gemfile
22
+ - Gemfile.lock
23
+ - LICENSE
24
+ - README.md
25
+ - examples/example.rb
26
+ - lib/s3_rotate.rb
27
+ - lib/s3_rotate/aws/s3_client.rb
28
+ - lib/s3_rotate/core/backup_manager.rb
29
+ - lib/s3_rotate/core/backup_rotator.rb
30
+ - lib/s3_rotate/core/backup_uploader.rb
31
+ - lib/s3_rotate/utils/file_utils.rb
32
+ - s3_rotate.gemspec
33
+ - spec/s3_rotate/aws/s3_client_spec.rb
34
+ - spec/s3_rotate/core/backup_manager_spec.rb
35
+ - spec/s3_rotate/core/backup_rotator_spec.rb
36
+ - spec/s3_rotate/core/backup_uploader_spec.rb
37
+ - spec/s3_rotate/utils/file_utils_spec.rb
38
+ - spec/s3_rotate/utils/mock/backup-2020-01-02.test
39
+ - spec/s3_rotate/utils/mock/backup-2020-01-03.test
40
+ - spec/s3_rotate/utils/mock/backup-2020-02-01.test
41
+ - spec/s3_rotate/utils/mock/backup-2021-01-01.test
42
+ - spec/spec_helper.rb
43
+ homepage: https://github.com/Whova/s3_rotate
44
+ licenses:
45
+ - MIT
46
+ metadata: {}
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ requirements: []
62
+ rubygems_version: 3.0.1
63
+ signing_key:
64
+ specification_version: 4
65
+ summary: AWS S3 upload with rotation mechanism
66
+ test_files:
67
+ - spec/s3_rotate/aws/s3_client_spec.rb
68
+ - spec/s3_rotate/core/backup_manager_spec.rb
69
+ - spec/s3_rotate/core/backup_rotator_spec.rb
70
+ - spec/s3_rotate/core/backup_uploader_spec.rb
71
+ - spec/s3_rotate/utils/file_utils_spec.rb
72
+ - spec/s3_rotate/utils/mock/backup-2020-01-02.test
73
+ - spec/s3_rotate/utils/mock/backup-2020-01-03.test
74
+ - spec/s3_rotate/utils/mock/backup-2020-02-01.test
75
+ - spec/s3_rotate/utils/mock/backup-2021-01-01.test
76
+ - spec/spec_helper.rb