martilla 0.0.1 → 0.2.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.
- 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
|