backups-cli 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,54 @@
1
+ module Backups
2
+ module System
3
+
4
+ def exec command
5
+ # $LOGGER.debug "Running #{command}" if $LOG_ACTIVE == 1
6
+ return if $DRY_RUN
7
+
8
+ output = `#{command}`
9
+ if $?.exitstatus != 0
10
+ raise RuntimeError, \
11
+ "Command '#{command}' failed with exit code #{$?.exitstatus}."
12
+ end
13
+
14
+ return output.chomp()
15
+ end
16
+
17
+ def delete file
18
+ exec "rm #{file}"
19
+ end
20
+
21
+ def delete_dir start, stop = nil
22
+ return exec "rmdir #{start}" unless stop
23
+ stop = stop.chomp("/")
24
+ loop do
25
+ exec "rmdir #{start}" if File.directory? start
26
+ break if start == stop
27
+ start = File.dirname(start)
28
+ end
29
+ end
30
+
31
+ def nuke_dir dir
32
+ exec "rm -fr #{dir}"
33
+ end
34
+
35
+ def mkdir dirname
36
+ exec "mkdir -p #{dirname}"
37
+ end
38
+
39
+ def write filename, contents
40
+ commands = []
41
+ commands << "cat << CONTENTS > #{filename}"
42
+ commands << contents
43
+ commands << "CONTENTS"
44
+
45
+ exec commands.join("\n")
46
+ end
47
+
48
+ def get_latest_s3 path
49
+ # $LOGGER.debug "aws s3 ls #{path}/|awk '{ print $4 }'|tail -n 1"
50
+ exec "aws s3 ls #{path}/|awk '{ print $4 }'|tail -n 1"
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,180 @@
1
+ require "yaml"
2
+
3
+ module Backups
4
+ module Verify
5
+ class Mysql < Base
6
+
7
+ VERIFY_PREFIX = "__verify__"
8
+
9
+ include ::Backups::Stats::Mysql
10
+
11
+ def verify
12
+ setup
13
+ download
14
+ import
15
+ clean_up
16
+ report
17
+
18
+ return @details
19
+ end
20
+
21
+ private
22
+ def setup
23
+ load_configs
24
+
25
+ @compared = 0
26
+ @failures = 0
27
+ @compsize = nil
28
+ @datedir = get_date_path()
29
+ @backups = $GLOBAL.fetch("backups", {})
30
+ @name = @config["_name"]
31
+ @verify = @config.fetch("verify", {})
32
+ @connection = @verify.fetch("connection", {})
33
+ @secret = @config.fetch("encryption", {}).fetch("secret", "")
34
+ @paths = @backups.fetch("paths", {})
35
+ @verifydir = @paths.fetch("verify", "/tmp/verify")
36
+ @jobdir = "#{@verifydir}/#{@name}"
37
+ @s3bucket = "#{@config["s3"]["bucket"]}"
38
+ @s3path = "#{@config["s3"]["path"]}"
39
+ @s3fullpath = "s3://#{@s3bucket}/#{@s3path}/#{@name}/#{@datedir}"
40
+ @package = get_latest_s3(@s3fullpath)
41
+
42
+ raise RuntimeError, "Error: Could not found the latest package in #{@s3fullpath}." \
43
+ unless @package.length > 1
44
+
45
+ @s3file = "#{@s3fullpath}/#{@package}"
46
+ @basename = File.basename(@package).gsub(".zip", "")
47
+ @download = "#{@jobdir}/#{@package}"
48
+ @timedir = @download.gsub(".zip", "")
49
+
50
+ @details = {
51
+ started: Time.now,
52
+ completed: nil,
53
+ file: nil,
54
+ size: nil,
55
+ report: nil,
56
+ }
57
+
58
+ $LOGGER.info "Preparing #{@jobdir}"
59
+ # We clean up previous imports as we are less strict with them clearing
60
+ # up cleanly.
61
+ exec "rm -fr #{@jobdir}"
62
+ exec "mkdir -p #{@jobdir}"
63
+ end
64
+
65
+ def download
66
+ $LOGGER.info "Downloading #{@s3file}"
67
+ exec "aws s3 cp #{@s3file} #{@download}"
68
+ @compsize = File.size(@download) if not $DRY_RUN
69
+ exec "cd #{@jobdir} && unzip -P #{@secret} #{@download}"
70
+ $LOGGER.info "Downloaded #{@compsize} bytes"
71
+ end
72
+
73
+ def import
74
+ files = get_import_files()
75
+
76
+ if files == []
77
+ $LOGGER.fatal "Error: There were no files in #{@timedir} to import."
78
+ return
79
+ end
80
+
81
+ # Are we importing the whole server?
82
+ if File.basename(files[0], ".sql") == ALL_DATABASES
83
+ file = files[0]
84
+ import_server file
85
+ check_stats file
86
+ else
87
+ files.each do |file|
88
+ db = File.basename(file, ".sql")
89
+ dbname = "#{VERIFY_PREFIX}#{db}"
90
+ import_database dbname, file
91
+ check_database_stats dbname, file
92
+ drop_database dbname
93
+ end
94
+ end
95
+ end
96
+
97
+ def import_server file
98
+ $LOGGER.info "Importing server from #{file}"
99
+ exec "mysql < #{file}"
100
+ end
101
+
102
+ def import_database db, file
103
+ $LOGGER.info "Importing database #{db} from #{file}"
104
+ exec "mysql -e 'DROP DATABASE IF EXISTS #{db}'"
105
+ exec "mysql -e 'CREATE DATABASE #{db}'"
106
+ exec "mysql #{db} < #{file}"
107
+ end
108
+
109
+ def get_import_files
110
+ Dir["#{@timedir}/*.sql"]
111
+ end
112
+
113
+ def check_database_stats db, file
114
+ # return if db == "mysql"
115
+
116
+ file = file.gsub(".sql", "-stats.yaml")
117
+ data = YAML.load_file(file)
118
+
119
+ data.each do |table, stats|
120
+ object = "#{db}.#{table}"
121
+ check_table db, table
122
+
123
+ imported = get_table_count(db, table)
124
+ saved = stats["rows"]
125
+
126
+ @compared = @compared + 1
127
+ if saved.to_i == imported.to_i
128
+ $LOGGER.debug "Row count match for #{object} matches"
129
+ else
130
+ $LOGGER.warn "Row count failed for #{object}. Saved #{saved} vs imported #{imported}"
131
+ end
132
+ end
133
+ end
134
+
135
+ def get_table_count db, table
136
+ sql = "SELECT COUNT(1) FROM #{db}.#{table}"
137
+ exec "mysql -e \"#{sql}\"|awk 'NR>1'"
138
+ end
139
+
140
+ def drop_database db
141
+ $LOGGER.debug "Dropping database #{db}"
142
+ sql = "DROP DATABASE #{db}"
143
+ exec "mysql -e '#{sql}'"
144
+ end
145
+
146
+ def check_table database, table
147
+ @compared = @compared + 1
148
+ rs = get_result("CHECK TABLE #{database}.#{table}")
149
+ if rs["Msg_text"] != "OK"
150
+ @failures += 1
151
+ $LOGGER.warn "Check table failed for #{database}.#{table}"
152
+ else
153
+ $LOGGER.debug "Check table passed for #{database}.#{table}"
154
+ end
155
+ end
156
+
157
+ def clean_up
158
+ $LOGGER.info "Cleaning #{@jobdir}"
159
+ @compsize = File.size(@download)
160
+ exec "rm -fr #{@jobdir}"
161
+ end
162
+
163
+ def report
164
+ $LOGGER.info "Reporting that #{@compared} checks were compared"
165
+ if @failures > 0
166
+ $LOGGER.warn "#{@failures} checks failed"
167
+ else
168
+ $LOGGER.info "All checks passed"
169
+ end
170
+
171
+ @details[:file] = @download
172
+ @details[:size] = @compsize
173
+ @details[:view] = "https://console.aws.amazon.com/s3/home?region=eu-west-1#&bucket=#{@s3bucket}&prefix=#{@s3path}"
174
+ @details[:report] = "#{@compared} stats compared with #{@failures} failures"
175
+ @details[:completed] = Time.now
176
+ end
177
+
178
+ end
179
+ end
180
+ end
@@ -0,0 +1,4 @@
1
+
2
+ module Backups
3
+ VERSION = "1.0.9"
4
+ end
metadata ADDED
@@ -0,0 +1,173 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: backups-cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.9
5
+ platform: ruby
6
+ authors:
7
+ - Schibsted
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-03-19 00:00:00.000000000 Z
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
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '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'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mysql2
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
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: dogapi
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: slack-notifier
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: tablelize
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: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: This tool backups different data sources to S3.
112
+ email:
113
+ - spt@schibsted.com
114
+ executables:
115
+ - backups
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".gitignore"
120
+ - ".travis.yml"
121
+ - Gemfile
122
+ - LICENSE
123
+ - README.md
124
+ - Rakefile
125
+ - backups-cli.gemspec
126
+ - bin/backups
127
+ - lib/backups.rb
128
+ - lib/backups/adapter/mysql.rb
129
+ - lib/backups/base.rb
130
+ - lib/backups/cli.rb
131
+ - lib/backups/crontab.rb
132
+ - lib/backups/driver/mysql.rb
133
+ - lib/backups/events.rb
134
+ - lib/backups/ext/fixnum.rb
135
+ - lib/backups/ext/hash.rb
136
+ - lib/backups/ext/nil_class.rb
137
+ - lib/backups/ext/ordered_hash.rb
138
+ - lib/backups/ext/string.rb
139
+ - lib/backups/listener.rb
140
+ - lib/backups/listeners/notify/datadog.rb
141
+ - lib/backups/listeners/notify/slack.rb
142
+ - lib/backups/loader.rb
143
+ - lib/backups/logger.rb
144
+ - lib/backups/runner.rb
145
+ - lib/backups/stats/mysql.rb
146
+ - lib/backups/system.rb
147
+ - lib/backups/verify/mysql.rb
148
+ - lib/backups/version.rb
149
+ homepage: https://github.com/schibsted/backups-cli
150
+ licenses:
151
+ - MIT
152
+ metadata: {}
153
+ post_install_message:
154
+ rdoc_options: []
155
+ require_paths:
156
+ - lib
157
+ required_ruby_version: !ruby/object:Gem::Requirement
158
+ requirements:
159
+ - - ">="
160
+ - !ruby/object:Gem::Version
161
+ version: '0'
162
+ required_rubygems_version: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ requirements: []
168
+ rubyforge_project:
169
+ rubygems_version: 2.5.2.1
170
+ signing_key:
171
+ specification_version: 4
172
+ summary: This tool backups different data sources to S3
173
+ test_files: []