rds_backup 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 72effc5ca22b06b2b27abaab144db3418a747193
4
+ data.tar.gz: 8e44fc0fe5edea2e7ba6dcc03c607e093287507b
5
+ SHA512:
6
+ metadata.gz: 3807fb41057c41f7b8c8490258f29035c868c2965c06b8f1efb9d3c820464b2fbcb893960e3a7886b720d6070b8567e0a668d0bd6977baed97168d7c6646d364
7
+ data.tar.gz: be97982df38a7589e76ffe9aeb26dd1bd2ed889074cd910c5105d2de5093801d5732fe77d2beefb525adbf010040d6662d6e04f192a75c86dfd47c78c1af6a13
@@ -0,0 +1,38 @@
1
+ # Project specific
2
+ config.yml
3
+
4
+ # Ruby
5
+ *.gem
6
+ *.rbc
7
+ /.config
8
+ /coverage/
9
+ /InstalledFiles
10
+ /pkg/
11
+ /spec/reports/
12
+ /test/tmp/
13
+ /test/version_tmp/
14
+ /tmp/
15
+
16
+ ## Specific to RubyMotion:
17
+ .dat*
18
+ .repl_history
19
+ build/
20
+
21
+ ## Documentation cache and generated files:
22
+ /.yardoc/
23
+ /_yardoc/
24
+ /doc/
25
+ /rdoc/
26
+
27
+ ## Environment normalisation:
28
+ /.bundle/
29
+ /lib/bundler/man/
30
+
31
+ # for a library or gem, you might want to ignore these files since the code is
32
+ # intended to run in multiple environments; otherwise, check them in:
33
+ # Gemfile.lock
34
+ # .ruby-version
35
+ # .ruby-gemset
36
+
37
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
38
+ .rvmrc
@@ -0,0 +1,2 @@
1
+ Documentation:
2
+ Enabled: false
@@ -0,0 +1 @@
1
+ 2.1.2
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,75 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ aws-sdk (1.51.0)
5
+ json (~> 1.4)
6
+ nokogiri (>= 1.4.4)
7
+ builder (3.2.2)
8
+ byebug (2.7.0)
9
+ columnize (~> 0.3)
10
+ debugger-linecache (~> 1.2)
11
+ coderay (1.1.0)
12
+ columnize (0.8.9)
13
+ debugger-linecache (1.2.0)
14
+ excon (0.39.5)
15
+ fog (1.23.0)
16
+ fog-brightbox
17
+ fog-core (~> 1.23)
18
+ fog-json
19
+ fog-softlayer
20
+ ipaddress (~> 0.5)
21
+ nokogiri (~> 1.5, >= 1.5.11)
22
+ fog-brightbox (0.3.0)
23
+ fog-core (~> 1.22)
24
+ fog-json
25
+ inflecto
26
+ fog-core (1.23.0)
27
+ builder
28
+ excon (~> 0.38)
29
+ formatador (~> 0.2)
30
+ mime-types
31
+ net-scp (~> 1.1)
32
+ net-ssh (>= 2.1.3)
33
+ fog-json (1.0.0)
34
+ multi_json (~> 1.0)
35
+ fog-softlayer (0.3.14)
36
+ fog-core
37
+ fog-json
38
+ formatador (0.2.5)
39
+ hipchat (1.3.0)
40
+ httparty
41
+ httparty (0.13.1)
42
+ json (~> 1.8)
43
+ multi_xml (>= 0.5.2)
44
+ inflecto (0.0.2)
45
+ ipaddress (0.8.0)
46
+ json (1.8.1)
47
+ method_source (0.8.2)
48
+ mime-types (2.3)
49
+ mini_portile (0.6.0)
50
+ multi_json (1.10.1)
51
+ multi_xml (0.5.5)
52
+ net-scp (1.2.1)
53
+ net-ssh (>= 2.6.5)
54
+ net-ssh (2.9.1)
55
+ nokogiri (1.6.3.1)
56
+ mini_portile (= 0.6.0)
57
+ pry (0.10.1)
58
+ coderay (~> 1.1.0)
59
+ method_source (~> 0.8.1)
60
+ slop (~> 3.4)
61
+ pry-byebug (1.3.3)
62
+ byebug (~> 2.7)
63
+ pry (~> 0.10)
64
+ slop (3.6.0)
65
+ yell (2.0.4)
66
+
67
+ PLATFORMS
68
+ ruby
69
+
70
+ DEPENDENCIES
71
+ aws-sdk
72
+ fog
73
+ hipchat
74
+ pry-byebug
75
+ yell
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 IDXP Analytics Inc.
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,48 @@
1
+ # RDS Backup
2
+
3
+ This gem backs up RDS databases to different cloud providers, granting an extra level of mind peacefulness.
4
+
5
+ ## Installation
6
+
7
+ `rds_backup` should be run as a command line tool, so it makes sense to install it globally
8
+
9
+ ```bash
10
+ $ gem install rds_backup
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ `rds_backup` expects a `config.yml` file on the folder it is run, [here is a sample](config.yml.sample).
16
+
17
+ Currently, you need a Google Cloud account with access to Cloud Storage. Sign up [here](https://developers.google.com/storage/docs/signup?csw=1) and get your credentials [here](https://storage.cloud.google.com/m) under the section "Interoperable Access".
18
+
19
+ AWS credentials with access to SES and a Hipchat Room token from API v2 are also required at this time.
20
+
21
+ Then, simply run the gem's binary:
22
+
23
+ ```bash
24
+ $ rds_backup
25
+ ```
26
+
27
+ ### Cron Usage
28
+
29
+ This tool is usually scheduled in cron, below is an example
30
+
31
+ ```
32
+ 0 3 * * * . $HOME/.profile; cd $HOME/rds_backup && rds_backup >> /var/log/rds_backup/rds_backup.log 2>&1
33
+ ```
34
+
35
+ ## Roadmap
36
+
37
+ * Tests
38
+ * Multiple cloud providers (we're already using fog)
39
+ * More yell adapters (Slack, Campfire, IRC, etc)
40
+ * More flexibe rules on backups to keep (à la [ec2-expire-snapshots](https://github.com/alestic/ec2-expire-snapshots))
41
+
42
+ ## Contributing
43
+
44
+ 1. Fork it
45
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
46
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
47
+ 4. Push to the branch (`git push origin my-new-feature`)
48
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ require 'rds_backup'
5
+ rescue LoadError
6
+ require 'rubygems'
7
+ require 'rds_backup'
8
+ end
9
+
10
+ rb = RdsBackup::Backup.new
11
+ rb.backup
@@ -0,0 +1,25 @@
1
+ cloud_storage:
2
+ access_key_id:
3
+ secret_access_key:
4
+ mysql:
5
+ user:
6
+ password:
7
+ host:
8
+ database:
9
+ ssl: false
10
+ rds_cert_path: /home/user/rds_backup/mysql-ssl-ca-cert.pem
11
+ aws:
12
+ access_key_id:
13
+ secret_access_key:
14
+ email:
15
+ from_address: no-reply@example.com
16
+ to_addresses:
17
+ - git@example.com
18
+ subject: 'RDS Backup'
19
+ hipchat:
20
+ token:
21
+ rooms:
22
+ - Test
23
+ loggers:
24
+ - ses
25
+ - hipchat
@@ -0,0 +1,4 @@
1
+ require 'rds_backup/backup'
2
+
3
+ module RdsBackup
4
+ end
@@ -0,0 +1,123 @@
1
+ require 'fog'
2
+ require 'open3'
3
+ require 'yaml'
4
+ require_relative '../yell_adapters/ses_adapter'
5
+ require_relative '../yell_adapters/hipchat_adapter'
6
+
7
+ module RdsBackup
8
+ class Backup
9
+ def initialize(config_file = 'config.yml')
10
+ config = YAML.load(File.open(config_file))
11
+ config_google(config)
12
+ config_mysql(config)
13
+ config_logger(config)
14
+
15
+ @backups_to_keep = config['backups_to_keep'] || 3
16
+ current_utc_time = Time.now.getutc.strftime('%Y%m%d%H%M%S')
17
+ @file_name = "#{mysql_database}-#{current_utc_time}.sql.gz"
18
+ end
19
+
20
+ def backup
21
+ logger.info 'Starting...'
22
+ dump_database
23
+ upload_backup
24
+ prune_old_backups
25
+ remove_local_dump
26
+ ensure
27
+ logger.info 'Exiting...'
28
+ logger.close
29
+ end
30
+
31
+ private
32
+
33
+ attr_accessor :mysql_database, :mysql_host, :mysql_user, :mysql_password,
34
+ :mysql_ssl, :rds_cert_path, :fog_directory, :file_name,
35
+ :backups_to_keep, :logger
36
+
37
+ def config_mysql(config)
38
+ @mysql_database = config['mysql']['database']
39
+ @mysql_host = config['mysql']['host']
40
+ @mysql_user = config['mysql']['user']
41
+ @mysql_password = config['mysql']['password']
42
+ @mysql_ssl = config['mysql']['ssl']
43
+ @rds_cert_path = config['mysql']['rds_cert_path'] if @mysql_ssl
44
+ end
45
+
46
+ def config_google(config)
47
+ google_access = config['cloud_storage']['access_key_id']
48
+ google_secret = config['cloud_storage']['secret_access_key']
49
+ connection = Fog::Storage.new(
50
+ provider: 'Google',
51
+ google_storage_access_key_id: google_access,
52
+ google_storage_secret_access_key: google_secret
53
+ )
54
+ @fog_directory = connection.directories.get('idxp-rds-backup')
55
+ end
56
+
57
+ def config_logger(config)
58
+ @logger = Yell.new do |yell_logger|
59
+ config['loggers'].each do |logger|
60
+ send("config_#{logger}_adapter", yell_logger, config)
61
+ end
62
+ end
63
+ end
64
+
65
+ def config_ses_adapter(logger, config)
66
+ logger.adapter :ses_adapter,
67
+ format: Yell::BasicFormat,
68
+ aws_access_key_id: config['aws']['access_key_id'],
69
+ aws_secret_access_key: config['aws']['secret_access_key'],
70
+ email_config: config['email']
71
+ end
72
+
73
+ def config_hipchat_adapter(logger, config)
74
+ logger.adapter :hipchat_adapter,
75
+ format: Yell::BasicFormat,
76
+ hipchat_token: config['hipchat']['token'],
77
+ hipchat_rooms: config['hipchat']['rooms']
78
+ end
79
+
80
+ def dump_database
81
+ _out, err, _status = Open3.capture3 mysqldump_cmd
82
+
83
+ if err.empty?
84
+ logger.info 'Database dump successfully created'
85
+ else
86
+ logger.error "Error when dumping the database: #{err.strip}"
87
+ remove_local_dump
88
+ fail RuntimeError
89
+ end
90
+ end
91
+
92
+ def mysqldump_cmd
93
+ cmd = "mysqldump -u#{mysql_user} "
94
+ cmd += "-p#{mysql_password} " if mysql_password
95
+ cmd += "--ssl_ca=#{rds_cert_path} " if mysql_ssl
96
+ cmd += '--single-transaction --routines --triggers '\
97
+ "-h #{mysql_host} #{mysql_database} "\
98
+ "| gzip -c > #{file_name}"
99
+ cmd
100
+ end
101
+
102
+ def upload_backup
103
+ fog_directory.files.create(key: file_name, body: File.open(file_name))
104
+ logger.info 'Backup uploaded to Google'
105
+ rescue
106
+ logger.error 'Error while uploading dump to Google'
107
+ end
108
+
109
+ def prune_old_backups
110
+ sorted_files = fog_directory.files.reload.sort do |x, y|
111
+ x.last_modified <=> y.last_modified
112
+ end
113
+ sorted_files[0 .. -backups_to_keep - 1].each { |f| f.destroy }
114
+ logger.info 'Old backups pruned'
115
+ rescue
116
+ logger.error 'Error while pruning old backups'
117
+ end
118
+
119
+ def remove_local_dump
120
+ Open3.capture3 "rm -rf #{file_name}"
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,3 @@
1
+ module RdsBackup
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,47 @@
1
+ require 'yell'
2
+ require 'hipchat'
3
+
4
+ class HipchatAdapter < Yell::Adapters::Base
5
+ include Yell::Helpers::Base
6
+ include Yell::Helpers::Formatter
7
+
8
+ attr_accessor :hipchat, :body_text, :hipchat_rooms, :errors
9
+
10
+ setup do |options|
11
+ self.formatter = options[:format]
12
+ self.hipchat = HipChat::Client.new(
13
+ options[:hipchat_token], api_version: 'v2'
14
+ )
15
+ self.hipchat_rooms = options[:hipchat_rooms]
16
+ self.body_text = ''
17
+ self.errors = false
18
+ end
19
+
20
+ write do |event|
21
+ self.body_text += formatter.call(event)
22
+ self.errors = true if event.level >= 3
23
+ end
24
+
25
+ close do
26
+ format_body_text_to_html
27
+ color = errors? ? 'red' : 'green'
28
+ hipchat_rooms.each do |room|
29
+ hipchat[room].send('RDS Backup', body_text, message_format: 'html',
30
+ color: color)
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def errors?
37
+ errors
38
+ end
39
+
40
+ def format_body_text_to_html
41
+ body_text.gsub!("\n", '<br>')
42
+ prepend = errors? ? '<strong>Error!</strong>' : '<strong>Success!</strong>'
43
+ self.body_text = [prepend, body_text].join '<br>'
44
+ end
45
+ end
46
+
47
+ Yell::Adapters.register :hipchat_adapter, HipchatAdapter
@@ -0,0 +1,48 @@
1
+ require 'yell'
2
+ require 'aws-sdk'
3
+
4
+ class SesAdapter < Yell::Adapters::Base
5
+ include Yell::Helpers::Base
6
+ include Yell::Helpers::Formatter
7
+
8
+ attr_accessor :ses, :body_text, :email_config, :errors
9
+
10
+ setup do |options|
11
+ self.formatter = options[:format]
12
+ self.ses = AWS::SimpleEmailService.new(
13
+ access_key_id: options[:aws_access_key_id],
14
+ secret_access_key: options[:aws_secret_access_key]
15
+ )
16
+ self.email_config = options[:email_config]
17
+ self.body_text = ''
18
+ self.errors = false
19
+ end
20
+
21
+ write do |event|
22
+ self.body_text += formatter.call(event)
23
+ self.errors = true if event.level >= 3
24
+ end
25
+
26
+ close do
27
+ base_subject = email_config['subject'] + Time.now.utc.strftime(' %Y/%m/%d')
28
+ subject = format_subject(base_subject)
29
+ ses.send_email(
30
+ subject: subject,
31
+ from: email_config['from_address'],
32
+ to: email_config['to_addresses'],
33
+ body_text: body_text
34
+ )
35
+ end
36
+
37
+ private
38
+
39
+ def errors?
40
+ errors
41
+ end
42
+
43
+ def format_subject(base_subject)
44
+ errors? ? "Error: #{base_subject}" : "Sucess: #{base_subject}"
45
+ end
46
+ end
47
+
48
+ Yell::Adapters.register :ses_adapter, SesAdapter
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rds_backup/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'rds_backup'
8
+ spec.version = RdsBackup::VERSION
9
+ spec.authors = ['Artur Rodrigues']
10
+ spec.email = ['arturhoo@gmail.com']
11
+ spec.description = 'Backs up RDS Databases and sync them to multiple '\
12
+ 'cloud providers'
13
+ spec.summary = 'Offsite and offprovider backups for RDS Databases'
14
+ spec.homepage = 'https://github.com/idxp/rds_backup'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
18
+ spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(/^(test|spec|features)\//)
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_development_dependency 'bundler', '~> 1.3'
23
+ spec.add_development_dependency 'pry'
24
+ spec.add_development_dependency 'pry_byebug'
25
+
26
+ spec.add_dependency 'aws-sdk'
27
+ spec.add_dependency 'fog'
28
+ spec.add_dependency 'yell'
29
+ spec.add_dependency 'hipchat'
30
+ end
metadata ADDED
@@ -0,0 +1,159 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rds_backup
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Artur Rodrigues
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-09-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry_byebug
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: aws-sdk
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: fog
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: yell
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: hipchat
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Backs up RDS Databases and sync them to multiple cloud providers
112
+ email:
113
+ - arturhoo@gmail.com
114
+ executables:
115
+ - rds_backup
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".gitignore"
120
+ - ".rubocop.yml"
121
+ - ".ruby-version"
122
+ - Gemfile
123
+ - Gemfile.lock
124
+ - LICENSE.md
125
+ - README.md
126
+ - Rakefile
127
+ - bin/rds_backup
128
+ - config.yml.sample
129
+ - lib/rds_backup.rb
130
+ - lib/rds_backup/backup.rb
131
+ - lib/rds_backup/version.rb
132
+ - lib/yell_adapters/hipchat_adapter.rb
133
+ - lib/yell_adapters/ses_adapter.rb
134
+ - rds_backup.gemspec
135
+ homepage: https://github.com/idxp/rds_backup
136
+ licenses:
137
+ - MIT
138
+ metadata: {}
139
+ post_install_message:
140
+ rdoc_options: []
141
+ require_paths:
142
+ - lib
143
+ required_ruby_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ requirements: []
154
+ rubyforge_project:
155
+ rubygems_version: 2.2.2
156
+ signing_key:
157
+ specification_version: 4
158
+ summary: Offsite and offprovider backups for RDS Databases
159
+ test_files: []