martilla 0.0.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +5 -0
- data/Gemfile.lock +44 -12
- data/README.md +124 -15
- data/config.yml +14 -0
- data/lib/martilla/backup.rb +115 -0
- data/lib/martilla/cli.rb +5 -3
- data/lib/martilla/database.rb +17 -6
- data/lib/martilla/databases/mysql.rb +37 -2
- data/lib/martilla/databases/postgres.rb +38 -2
- data/lib/martilla/notifier.rb +27 -8
- data/lib/martilla/notifiers/email_notifier.rb +65 -0
- data/lib/martilla/notifiers/sendmail.rb +21 -0
- data/lib/martilla/notifiers/ses.rb +86 -2
- data/lib/martilla/notifiers/slack.rb +2 -3
- data/lib/martilla/notifiers/smtp.rb +70 -0
- data/lib/martilla/storage.rb +47 -7
- data/lib/martilla/storages/local.rb +7 -3
- data/lib/martilla/storages/s3.rb +39 -2
- data/lib/martilla/storages/scp.rb +26 -2
- data/lib/martilla/utilities.rb +45 -0
- data/lib/martilla/version.rb +1 -1
- data/lib/martilla.rb +17 -24
- data/martilla.gemspec +7 -2
- metadata +84 -12
- data/lib/martilla/databases/base.rb +0 -11
- data/lib/martilla/notifiers/base.rb +0 -7
- data/lib/martilla/notifiers/email.rb +0 -5
- data/lib/martilla/storages/base.rb +0 -7
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'pony'
|
2
|
+
|
3
|
+
module Martilla
|
4
|
+
class Sendmail < EmailNotifier
|
5
|
+
def success(data)
|
6
|
+
Pony.mail(to: to_email,
|
7
|
+
from: from_email,
|
8
|
+
subject: success_subject,
|
9
|
+
html_body: success_html(data),
|
10
|
+
body: success_txt(data))
|
11
|
+
end
|
12
|
+
|
13
|
+
def error(msg, data)
|
14
|
+
Pony.mail(to: to_email,
|
15
|
+
from: from_email,
|
16
|
+
subject: failure_subject,
|
17
|
+
html_body: error_html(msg, data),
|
18
|
+
body: error_txt(msg, data))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,5 +1,89 @@
|
|
1
|
-
|
2
|
-
def notify(opts)
|
1
|
+
require 'aws-sdk-ses'
|
3
2
|
|
3
|
+
module Martilla
|
4
|
+
class Ses < EmailNotifier
|
5
|
+
def success(data)
|
6
|
+
begin
|
7
|
+
ses_client.send_email(
|
8
|
+
destination: {
|
9
|
+
to_addresses: to_email.split(',')
|
10
|
+
},
|
11
|
+
message: {
|
12
|
+
body: {
|
13
|
+
html: {
|
14
|
+
charset: 'UTF-8',
|
15
|
+
data: success_html(data)
|
16
|
+
},
|
17
|
+
text: {
|
18
|
+
charset: 'UTF-8',
|
19
|
+
data: success_txt(data)
|
20
|
+
}
|
21
|
+
},
|
22
|
+
subject: {
|
23
|
+
charset: 'UTF-8',
|
24
|
+
data: success_subject
|
25
|
+
}
|
26
|
+
},
|
27
|
+
source: from_email
|
28
|
+
)
|
29
|
+
rescue Aws::SES::Errors::ServiceError => error
|
30
|
+
puts "Email not sent. Error message: #{error}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def error(msg, data)
|
35
|
+
begin
|
36
|
+
ses_client.send_email(
|
37
|
+
destination: {
|
38
|
+
to_addresses: [
|
39
|
+
to_email.split(',')
|
40
|
+
]
|
41
|
+
},
|
42
|
+
message: {
|
43
|
+
body: {
|
44
|
+
html: {
|
45
|
+
charset: 'UTF-8',
|
46
|
+
data: error_html(msg, data)
|
47
|
+
},
|
48
|
+
text: {
|
49
|
+
charset: 'UTF-8',
|
50
|
+
data: error_txt(msg, data)
|
51
|
+
}
|
52
|
+
},
|
53
|
+
subject: {
|
54
|
+
charset: 'UTF-8',
|
55
|
+
data: failure_subject
|
56
|
+
}
|
57
|
+
},
|
58
|
+
source: from_email
|
59
|
+
)
|
60
|
+
rescue Aws::SES::Errors::ServiceError => error
|
61
|
+
puts "Email not sent. Error message: #{error}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def ses_client
|
68
|
+
options = {}
|
69
|
+
options[:region] = aws_region unless aws_region.nil?
|
70
|
+
options[:access_key_id] = aws_access_key unless aws_access_key.nil?
|
71
|
+
options[:secret_access_key] = aws_secret_key unless aws_secret_key.nil?
|
72
|
+
Aws::SES::Client.new(options)
|
73
|
+
end
|
74
|
+
|
75
|
+
def aws_region
|
76
|
+
aws_region = @options['region']
|
77
|
+
raise config_error('region') if aws_region.nil?
|
78
|
+
aws_region
|
79
|
+
end
|
80
|
+
|
81
|
+
def aws_access_key
|
82
|
+
@options['access_key_id']
|
83
|
+
end
|
84
|
+
|
85
|
+
def aws_secret_key
|
86
|
+
@options['secret_access_key']
|
87
|
+
end
|
4
88
|
end
|
5
89
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'pony'
|
2
|
+
|
3
|
+
module Martilla
|
4
|
+
class Smtp < EmailNotifier
|
5
|
+
def success(data)
|
6
|
+
Pony.mail(to: to_email,
|
7
|
+
from: from_email,
|
8
|
+
subject: success_subject,
|
9
|
+
via: :smtp,
|
10
|
+
html_body: success_html(data),
|
11
|
+
body: success_txt(data),
|
12
|
+
via_options: via_options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def error(msg, data)
|
16
|
+
Pony.mail(to: to_email,
|
17
|
+
from: from_email,
|
18
|
+
subject: failure_subject,
|
19
|
+
via: :smtp,
|
20
|
+
html_body: error_html(msg, data),
|
21
|
+
body: error_txt(msg, data),
|
22
|
+
via_options: via_options)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def via_options
|
28
|
+
{
|
29
|
+
address: address,
|
30
|
+
port: port,
|
31
|
+
user_name: user_name,
|
32
|
+
password: password,
|
33
|
+
authentication: authentication, # :plain, :login, :cram_md5, no auth by default
|
34
|
+
domain: domain # the HELO domain provided by the client to the server
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def address
|
39
|
+
email = @options['address']
|
40
|
+
raise config_error('address') if email.nil?
|
41
|
+
email
|
42
|
+
end
|
43
|
+
|
44
|
+
def domain
|
45
|
+
smtp_domain = @options['domain']
|
46
|
+
raise config_error('domain') if smtp_domain.nil?
|
47
|
+
smtp_domain
|
48
|
+
end
|
49
|
+
|
50
|
+
def user_name
|
51
|
+
smtp_user_name = @options['user_name']
|
52
|
+
raise config_error('user_name') if smtp_user_name.nil?
|
53
|
+
smtp_user_name
|
54
|
+
end
|
55
|
+
|
56
|
+
def password
|
57
|
+
smtp_password = @options['password']
|
58
|
+
raise config_error('password') if smtp_password.nil?
|
59
|
+
smtp_password
|
60
|
+
end
|
61
|
+
|
62
|
+
def port
|
63
|
+
@options['port'] || '25'
|
64
|
+
end
|
65
|
+
|
66
|
+
def authentication
|
67
|
+
@options['authentication'] || :plain
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/martilla/storage.rb
CHANGED
@@ -2,22 +2,62 @@ require 'forwardable'
|
|
2
2
|
|
3
3
|
module Martilla
|
4
4
|
class Storage
|
5
|
-
|
5
|
+
attr_reader :options
|
6
6
|
|
7
7
|
def initialize(config)
|
8
|
-
|
8
|
+
@options = config
|
9
|
+
raise Error.new(invalid_options_msg) if @options.nil?
|
10
|
+
end
|
11
|
+
|
12
|
+
def persist(temp_file:, gzip:)
|
13
|
+
raise NotImplementedError, 'You must implement the persist method'
|
14
|
+
end
|
15
|
+
|
16
|
+
def invalid_options_msg
|
17
|
+
'Storage configuration is invalid. Details here: https://github.com/fdoxyz/martilla'
|
18
|
+
end
|
19
|
+
|
20
|
+
def suffix?
|
21
|
+
return true if @options['suffix'].nil?
|
22
|
+
@options['suffix']
|
23
|
+
end
|
24
|
+
|
25
|
+
def output_filename(gzip)
|
26
|
+
filename = @options['filename'] || 'backup.sql'
|
27
|
+
filename = append_datetime_suffix(filename) if suffix?
|
28
|
+
filename = "#{filename}.gz" if gzip
|
29
|
+
filename
|
30
|
+
end
|
31
|
+
|
32
|
+
def append_datetime_suffix(filename)
|
33
|
+
dirname = File.dirname(filename)
|
34
|
+
basename = File.basename(filename, '.*')
|
35
|
+
|
36
|
+
# 'dir_with_name' is the original filename WITHOUT the extension
|
37
|
+
dir_with_name = "#{dirname}/#{basename}"
|
38
|
+
dir_with_name = basename if dirname == '.'
|
39
|
+
|
40
|
+
extension = filename.gsub(dir_with_name, '')
|
41
|
+
timestamp = Time.now.strftime("%Y-%m-%dT%H%M%S")
|
42
|
+
"#{dirname}/#{basename}_#{timestamp}#{extension}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def config_error(config_name)
|
46
|
+
Error.new("Storage adapter configuration requires #{config_name}. Details here: https://github.com/fdoxyz/martilla")
|
47
|
+
end
|
48
|
+
|
49
|
+
# When a new Storage is supported it needs to go here
|
50
|
+
def self.create(config = {})
|
9
51
|
case config['type'].downcase
|
10
52
|
when 'local'
|
11
|
-
|
53
|
+
Local.new(config['options'])
|
12
54
|
when 's3'
|
13
|
-
|
55
|
+
S3.new(config['options'])
|
14
56
|
when 'scp'
|
15
|
-
|
57
|
+
Scp.new(config['options'])
|
16
58
|
else
|
17
59
|
raise Error.new("Invalid Storage type: #{config['type']}")
|
18
60
|
end
|
19
61
|
end
|
20
|
-
|
21
|
-
def_delegators :@storage, :persist
|
22
62
|
end
|
23
63
|
end
|
@@ -1,5 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
module Martilla
|
2
|
+
class Local < Storage
|
3
|
+
def persist(tmp_file:, gzip:)
|
4
|
+
`mv #{tmp_file} #{output_filename(gzip)}`
|
5
|
+
return nil if $?.success?
|
6
|
+
raise Error.new("Local storage failed with code #{$?.exitstatus}")
|
7
|
+
end
|
4
8
|
end
|
5
9
|
end
|
data/lib/martilla/storages/s3.rb
CHANGED
@@ -1,5 +1,42 @@
|
|
1
|
-
|
2
|
-
def persist(filepath, opts)
|
1
|
+
require 'aws-sdk-s3'
|
3
2
|
|
3
|
+
module Martilla
|
4
|
+
class S3 < Storage
|
5
|
+
def persist(tmp_file:, gzip:)
|
6
|
+
path = output_filename(gzip)
|
7
|
+
obj = s3_resource.bucket(bucket_name).object(path)
|
8
|
+
|
9
|
+
# Upload it
|
10
|
+
return nil if obj.upload_file(tmp_file)
|
11
|
+
raise Error.new('Error uploading backup to bucket')
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def s3_resource
|
17
|
+
options = {}
|
18
|
+
options[:region] = aws_region unless aws_region.nil?
|
19
|
+
options[:access_key_id] = aws_access_key unless aws_access_key.nil?
|
20
|
+
options[:secret_access_key] = aws_secret_key unless aws_secret_key.nil?
|
21
|
+
Aws::S3::Resource.new(options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def aws_region
|
25
|
+
@options['region']
|
26
|
+
end
|
27
|
+
|
28
|
+
def aws_access_key
|
29
|
+
@options['access_key_id']
|
30
|
+
end
|
31
|
+
|
32
|
+
def aws_secret_key
|
33
|
+
@options['secret_access_key']
|
34
|
+
end
|
35
|
+
|
36
|
+
def bucket_name
|
37
|
+
bucket = @options['bucket']
|
38
|
+
raise config_error('bucket') if bucket.nil?
|
39
|
+
bucket
|
40
|
+
end
|
4
41
|
end
|
5
42
|
end
|
@@ -1,5 +1,29 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module Martilla
|
2
|
+
class Scp < Storage
|
3
|
+
def persist(tmp_file:, gzip:)
|
4
|
+
`scp -i #{identity_file} #{user}@#{host}:#{output_filename(gzip)}`
|
5
|
+
return nil if $?.success?
|
6
|
+
raise Error.new("SCP storage failed with code #{$?.exitstatus}")
|
7
|
+
end
|
3
8
|
|
9
|
+
private
|
10
|
+
|
11
|
+
def host
|
12
|
+
scp_host = @options['host']
|
13
|
+
raise config_error('host') if scp_host.nil?
|
14
|
+
scp_host
|
15
|
+
end
|
16
|
+
|
17
|
+
def user
|
18
|
+
scp_user = @options['user']
|
19
|
+
raise config_error('user') if scp_user.nil?
|
20
|
+
scp_user
|
21
|
+
end
|
22
|
+
|
23
|
+
def identity_file
|
24
|
+
file = @options['identity_file']
|
25
|
+
raise config_error('identity_file') if file.nil?
|
26
|
+
file
|
27
|
+
end
|
4
28
|
end
|
5
29
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Martilla
|
2
|
+
class Backup
|
3
|
+
module Utilities
|
4
|
+
def duration_format(seconds)
|
5
|
+
case seconds
|
6
|
+
when 0..59
|
7
|
+
# 22s
|
8
|
+
"#{seconds}s"
|
9
|
+
when 60..3599
|
10
|
+
# 18m 19s
|
11
|
+
"#{s_to_m(seconds)}m #{seconds % 60}s"
|
12
|
+
else
|
13
|
+
# 7h 9m 51s
|
14
|
+
"#{s_to_h(seconds)}h #{s_to_m(seconds)}m #{seconds % 60}s"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def s_to_m(seconds)
|
19
|
+
(seconds / 60) % 60
|
20
|
+
end
|
21
|
+
|
22
|
+
def s_to_h(seconds)
|
23
|
+
(seconds / 3600) % 3600
|
24
|
+
end
|
25
|
+
|
26
|
+
def formatted_file_size
|
27
|
+
return if @file_size.nil?
|
28
|
+
|
29
|
+
if @file_size <= 799_999
|
30
|
+
compressed_file_size = @file_size / 2**10
|
31
|
+
formatted_size = '%.2f' % compressed_file_size
|
32
|
+
"#{formatted_size} KB"
|
33
|
+
elsif @file_size <= 799_999_999
|
34
|
+
compressed_file_size = @file_size / 2**20
|
35
|
+
formatted_size = '%.2f' % compressed_file_size
|
36
|
+
"#{formatted_size} MB"
|
37
|
+
else
|
38
|
+
compressed_file_size = @file_size / 2**30
|
39
|
+
formatted_size = '%.2f' % compressed_file_size
|
40
|
+
"#{formatted_size} GB"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/martilla/version.rb
CHANGED
data/lib/martilla.rb
CHANGED
@@ -1,31 +1,24 @@
|
|
1
1
|
require 'martilla/version'
|
2
2
|
require 'martilla/cli'
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
require 'martilla/backup'
|
5
|
+
|
6
|
+
require 'martilla/database'
|
7
|
+
require 'martilla/databases/mysql'
|
8
|
+
require 'martilla/databases/postgres'
|
6
9
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
require 'martilla/notifier'
|
11
|
+
require 'martilla/notifiers/email_notifier'
|
12
|
+
require 'martilla/notifiers/smtp'
|
13
|
+
require 'martilla/notifiers/sendmail'
|
14
|
+
require 'martilla/notifiers/ses'
|
15
|
+
require 'martilla/notifiers/slack'
|
12
16
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
rescue Exception => e
|
18
|
-
puts "EXCEPTION RAISED: #{e.inspect}"
|
19
|
-
notifiers.each do |notifier|
|
20
|
-
notifier.error(e)
|
21
|
-
end
|
22
|
-
else
|
23
|
-
puts "SUCCESS"
|
24
|
-
notifiers.each do |notifier|
|
25
|
-
notifier.success
|
26
|
-
end
|
27
|
-
end
|
17
|
+
require 'martilla/storage'
|
18
|
+
require 'martilla/storages/local'
|
19
|
+
require 'martilla/storages/s3'
|
20
|
+
require 'martilla/storages/scp'
|
28
21
|
|
29
|
-
|
30
|
-
end
|
22
|
+
module Martilla
|
23
|
+
class Error < StandardError; end
|
31
24
|
end
|
data/martilla.gemspec
CHANGED
@@ -28,11 +28,16 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
29
29
|
spec.require_paths = ['lib']
|
30
30
|
|
31
|
-
spec.add_dependency 'pony', '~> 1.13'
|
32
|
-
spec.add_dependency 'aws-ses', '~> 0.6.0'
|
33
31
|
spec.add_dependency 'thor', '~> 0.20.3'
|
32
|
+
spec.add_dependency 'memoist', '~> 0.16.0'
|
33
|
+
spec.add_dependency 'pony', '~> 1.13'
|
34
|
+
spec.add_dependency 'aws-sdk-ses', '~> 1.26'
|
35
|
+
spec.add_dependency 'aws-sdk-s3', '~> 1.49'
|
34
36
|
|
35
37
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
36
38
|
spec.add_development_dependency 'rake', '~> 13.0'
|
37
39
|
spec.add_development_dependency 'rspec', '~> 3.9'
|
40
|
+
spec.add_development_dependency 'byebug', '~> 11.0'
|
41
|
+
spec.add_development_dependency 'pry-byebug', '~> 3.7'
|
42
|
+
spec.add_development_dependency 'simplecov', '~> 0.17.1'
|
38
43
|
end
|
metadata
CHANGED
@@ -1,15 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: martilla
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fernando Valverde
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-10-
|
11
|
+
date: 2019-10-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.20.3
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.20.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: memoist
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.16.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.16.0
|
13
41
|
- !ruby/object:Gem::Dependency
|
14
42
|
name: pony
|
15
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -25,33 +53,33 @@ dependencies:
|
|
25
53
|
- !ruby/object:Gem::Version
|
26
54
|
version: '1.13'
|
27
55
|
- !ruby/object:Gem::Dependency
|
28
|
-
name: aws-ses
|
56
|
+
name: aws-sdk-ses
|
29
57
|
requirement: !ruby/object:Gem::Requirement
|
30
58
|
requirements:
|
31
59
|
- - "~>"
|
32
60
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
61
|
+
version: '1.26'
|
34
62
|
type: :runtime
|
35
63
|
prerelease: false
|
36
64
|
version_requirements: !ruby/object:Gem::Requirement
|
37
65
|
requirements:
|
38
66
|
- - "~>"
|
39
67
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
68
|
+
version: '1.26'
|
41
69
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
70
|
+
name: aws-sdk-s3
|
43
71
|
requirement: !ruby/object:Gem::Requirement
|
44
72
|
requirements:
|
45
73
|
- - "~>"
|
46
74
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
75
|
+
version: '1.49'
|
48
76
|
type: :runtime
|
49
77
|
prerelease: false
|
50
78
|
version_requirements: !ruby/object:Gem::Requirement
|
51
79
|
requirements:
|
52
80
|
- - "~>"
|
53
81
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
82
|
+
version: '1.49'
|
55
83
|
- !ruby/object:Gem::Dependency
|
56
84
|
name: bundler
|
57
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,6 +122,48 @@ dependencies:
|
|
94
122
|
- - "~>"
|
95
123
|
- !ruby/object:Gem::Version
|
96
124
|
version: '3.9'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: byebug
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '11.0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '11.0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: pry-byebug
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '3.7'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '3.7'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: simplecov
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: 0.17.1
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: 0.17.1
|
97
167
|
description: ''
|
98
168
|
email:
|
99
169
|
- fdov88@gmail.com
|
@@ -113,22 +183,24 @@ files:
|
|
113
183
|
- bin/console
|
114
184
|
- bin/martilla
|
115
185
|
- bin/setup
|
186
|
+
- config.yml
|
116
187
|
- lib/martilla.rb
|
188
|
+
- lib/martilla/backup.rb
|
117
189
|
- lib/martilla/cli.rb
|
118
190
|
- lib/martilla/database.rb
|
119
|
-
- lib/martilla/databases/base.rb
|
120
191
|
- lib/martilla/databases/mysql.rb
|
121
192
|
- lib/martilla/databases/postgres.rb
|
122
193
|
- lib/martilla/notifier.rb
|
123
|
-
- lib/martilla/notifiers/
|
124
|
-
- lib/martilla/notifiers/
|
194
|
+
- lib/martilla/notifiers/email_notifier.rb
|
195
|
+
- lib/martilla/notifiers/sendmail.rb
|
125
196
|
- lib/martilla/notifiers/ses.rb
|
126
197
|
- lib/martilla/notifiers/slack.rb
|
198
|
+
- lib/martilla/notifiers/smtp.rb
|
127
199
|
- lib/martilla/storage.rb
|
128
|
-
- lib/martilla/storages/base.rb
|
129
200
|
- lib/martilla/storages/local.rb
|
130
201
|
- lib/martilla/storages/s3.rb
|
131
202
|
- lib/martilla/storages/scp.rb
|
203
|
+
- lib/martilla/utilities.rb
|
132
204
|
- lib/martilla/version.rb
|
133
205
|
- martilla.gemspec
|
134
206
|
homepage: https://github.com/fdoxyz/martilla
|