data_keeper 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9c4e8095729b6927bc11ae296fc30571577d1dfd5f5d910b1092f924981efa69
4
- data.tar.gz: bb646294c8847fd637b765fd6a2f16af605dabe656b663d2cb0e6f54ff396f79
3
+ metadata.gz: 268e784853f728ad8c4cefd36ca8cc2f09b2892ab8751f1eb0f16dc17bc72900
4
+ data.tar.gz: 62ea9b6a3bf57ae952417db4fd149365f56f4baf63f67839bde26d3d2f352464
5
5
  SHA512:
6
- metadata.gz: cd3696d94b9ef70bf108e8c77ee880e1b97e68989955c6c7975b4f9cea9196b95417a17e6b5bf6e3a9baf2047cd0a1db524e2bc8dd660d2576f10385f38a038d
7
- data.tar.gz: 1ecab9088e179625113bb3a490a83c60a16405924f527caa059ed1dc05c68527049f12cc985aa1280f6e094597903f5bf280420a21c98a1670eb527b4e766c52
6
+ metadata.gz: 8ea7c0182fb8698c7d9c2be973cf7d3def1845222027feb90107adda8d333488ef01318268f8ae1356c2bd45d89419cb908443b5a9037df359cf5fc63376fca7
7
+ data.tar.gz: 7110186baac099fe5ce341186b25594c4ad730a811bc4270c4cd8e1d14d3cf4858bce5eb8bed0e621152da6d5729223c4d47c4f74b8e558c9539bb5bfcecd0c1
data/README.md CHANGED
@@ -36,23 +36,37 @@ order to download these dumps later. Ex:
36
36
  DataKeeper.storage = DataKeeper::LocalStorage.new(
37
37
  local_store_dir: "/users/fredy/backups/...",
38
38
  remote_access: {
39
- type: "scp",
40
- host: "141.12.241.22",
41
- port: "8622",
42
- user: "fredy"
39
+ host: "10.10.10.10",
40
+ port: "22",
41
+ user: "user"
43
42
  }
44
43
  )
45
44
  ```
46
45
 
47
- Other storages, like S3, could be implemented, but currently this gem only ships with local storage.
48
- If you want to do your own, you can assign as an storage whatever object that responds to:
46
+ There's also support for storing the dumps in s3, using `DataKeeper::S3Storage` like in this example:
49
47
 
50
- - `#save(file, filename, dump_name)`, where file is a File object and filename a string. This method should save the given
51
- dump file.
48
+ ```ruby
49
+ DataKeeper.storage = DataKeeper::S3Storage.new(
50
+ bucket: 'bucket-name',
51
+ store_dir: 'dumps/',
52
+ acl: "private",
53
+ remote_access: {
54
+ access_key_id: Rails.application.credentials.access_key_id,
55
+ secret_access_key: Rails.application.credentials.secret_access_key,
56
+ region: 'eu-central-1'
57
+ }
58
+ )
59
+ ```
60
+
61
+
62
+ Other storages can be implemented. An storage can be any object that responds to those two methods:
63
+
64
+ - `#save(file, filename, dump_name)`, where file is a File object and filename and dump_name are strings.
65
+ This method should save the given dump file in the store.
52
66
 
53
67
  - `#retrieve(dump_name) { |file| (...) }`, which should retrieve the latest stored dump with the given dump_name.
54
- It should yield the given block passing the File object pointing to the retrieved dump file in the local filesystem,
55
- which is expected to be cleaned up on block termination.
68
+ It should yield the given block passing the `File` or `Tempfile` object pointing to the retrieved dump
69
+ file in the local filesystem, which is expected to be cleaned up on block termination.
56
70
 
57
71
 
58
72
  Then, declare some dumps to work with:
@@ -101,7 +115,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
101
115
 
102
116
  ## Contributing
103
117
 
104
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/data_keeper.
118
+ Bug reports and pull requests are welcome on GitHub at https://github.com/rogercampos/data_keeper.
105
119
 
106
120
 
107
121
  ## License
data/data_keeper.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.description = %q{Easy management of database dumps for dev env}
11
11
  spec.homepage = "https://github.com/rogercampos/data_keeper"
12
12
  spec.license = "MIT"
13
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
13
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
14
14
 
15
15
  spec.metadata["homepage_uri"] = spec.homepage
16
16
 
@@ -27,5 +27,4 @@ Gem::Specification.new do |spec|
27
27
  spec.add_dependency "terrapin", ">= 0.5.0"
28
28
  spec.add_dependency "sshkit", ">= 1.20.0"
29
29
  spec.add_dependency "rails", ">= 5.0.0"
30
-
31
30
  end
@@ -0,0 +1,103 @@
1
+ begin
2
+ require 'aws-sdk-s3'
3
+ rescue LoadError
4
+ raise "You must include the 'aws-sdk-s3' gem in your Gemfile in order to use this s3 storage."
5
+ end
6
+
7
+ module DataKeeper
8
+ class S3Storage
9
+ class Client
10
+ NoSuchKey = Class.new(StandardError)
11
+
12
+ def initialize(client_options:, bucket: nil)
13
+ @client_options = client_options
14
+ @client = Aws::S3::Client.new(client_options)
15
+ @bucket = bucket
16
+ end
17
+
18
+ def delete_files(file_paths)
19
+ @client.delete_objects(
20
+ bucket: @bucket,
21
+ delete: {
22
+ objects: file_paths.map { |key| { key: key } }
23
+ }
24
+ )
25
+ end
26
+
27
+ def list_contents(prefix = '')
28
+ @client.list_objects(bucket: @bucket, prefix: prefix).contents
29
+ rescue Aws::S3::Errors::NoSuchKey
30
+ raise NoSuchKey, prefix
31
+ end
32
+
33
+ # Streams all contents from `path` into the provided io object, calling #write to it.
34
+ # io can be a File, or any other IO-like object.
35
+ def stream_to_io(path, io, opts = {})
36
+ @client.get_object(opts.merge(
37
+ bucket: @bucket,
38
+ key: path
39
+ ), target: io)
40
+ rescue Aws::S3::Errors::NoSuchKey
41
+ raise NoSuchKey, path
42
+ end
43
+
44
+ # Uploads the given file into the target_path in the s3 bucket.
45
+ # `file` must be a file stored locally. Can be either a raw string (path),
46
+ # or a File/Tempfile object (close is up to you).
47
+ def put_file(target_path, file, options = {})
48
+ file.rewind if file.respond_to?(:rewind)
49
+
50
+ s3 = Aws::S3::Resource.new(@client_options)
51
+ obj = s3.bucket(@bucket).object(target_path)
52
+ obj.upload_file(file, options)
53
+ end
54
+ end
55
+
56
+ def initialize(bucket:, store_dir:, remote_access:, acl: "public-read", keep_amount: 3)
57
+ @bucket = bucket
58
+ @store_dir = store_dir
59
+ @remote_access = remote_access
60
+ @acl = acl
61
+ @keep_amount = keep_amount
62
+ end
63
+
64
+ def save(file, filename, dump_name)
65
+ path = dump_path(dump_name, filename)
66
+
67
+ s3_client.put_file(path, file, acl: @acl)
68
+
69
+ prefix = "#{@store_dir}#{dump_name.to_s}"
70
+
71
+ keys_to_delete = s3_client.list_contents(prefix).sort_by(&:last_modified).reverse[@keep_amount..-1]
72
+
73
+ return unless keys_to_delete
74
+
75
+ s3_client.delete_files(keys_to_delete.map(&:key))
76
+
77
+ true
78
+ end
79
+
80
+ def retrieve(dump_name)
81
+ prefix = "#{@store_dir}#{dump_name.to_s}"
82
+ last_dump = s3_client.list_contents(prefix).sort_by(&:last_modified).reverse.first
83
+
84
+ Tempfile.create do |tmp_file|
85
+ tmp_file.binmode
86
+ s3_client.stream_to_io(last_dump.key, tmp_file)
87
+ tmp_file.flush
88
+
89
+ yield(tmp_file)
90
+ end
91
+ end
92
+
93
+ private
94
+
95
+ def s3_client
96
+ @s3_client ||= Client.new(bucket: @bucket, client_options: @remote_access)
97
+ end
98
+
99
+ def dump_path(dump_name, filename)
100
+ File.join(@store_dir, dump_name.to_s, "#{SecureRandom.alphanumeric(40)}-#{filename}")
101
+ end
102
+ end
103
+ end
@@ -1,3 +1,3 @@
1
1
  module DataKeeper
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: data_keeper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roger Campos
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-09 00:00:00.000000000 Z
11
+ date: 2021-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -91,6 +91,7 @@ files:
91
91
  - lib/data_keeper/loader.rb
92
92
  - lib/data_keeper/local_storage.rb
93
93
  - lib/data_keeper/railtie.rb
94
+ - lib/data_keeper/s3_storage.rb
94
95
  - lib/data_keeper/tasks/data_keeper.rake
95
96
  - lib/data_keeper/version.rb
96
97
  - todo.md
@@ -107,7 +108,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
107
108
  requirements:
108
109
  - - ">="
109
110
  - !ruby/object:Gem::Version
110
- version: 2.3.0
111
+ version: 2.5.0
111
112
  required_rubygems_version: !ruby/object:Gem::Requirement
112
113
  requirements:
113
114
  - - ">="