data_keeper 0.1.0 → 0.1.1

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 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
  - - ">="