mys3ql 1.0.0 → 1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5c654cea5796fd8510c97cadadfd2eec223711f0b9c67c71b6050af4a79e7223
4
+ data.tar.gz: 621782acd4a75e1be1c292621bae70aeecfc758a95a364de5201ed5f42c1b79a
5
+ SHA512:
6
+ metadata.gz: 7288bf4d3b1f9a208d19486ca5e7d8515fb3a97b1a66dee603f44c4571e8937c1a743a66963610f3dd744136aaa7fa506b44171c94bb9272253c69e09e50aa2c
7
+ data.tar.gz: 01a4dc81218fd10dd69f4770e6aeb933e634360033d6adcb85ca4a48528e8c101e60f25ec29223506b96dfb321f91cc5fdbe7999e12fde8458f5a22fbbb9c6cb
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Simple backup of your MySQL database onto Amazon S3.
4
4
 
5
+ See [Example: mysqldump + mysqlbinlog for Backup and Restore](https://dev.mysql.com/doc/refman/5.7/en/mysqlbinlog-backup.html#mysqlbinlog-backup-example).
6
+
5
7
 
6
8
  ## Quick start
7
9
 
@@ -52,6 +54,9 @@ Second, create your config file:
52
54
  secret_access_key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
53
55
  # Bucket in which to store your backups
54
56
  bucket: db_backups
57
+ # AWS region your bucket lives in.
58
+ # (I suspect you only need to specify this when your 'location' is in a different region.)
59
+ #region: eu-west-1
55
60
 
56
61
  If you only have one database to back up on your server, you can put the config file at `~/.mys3ql`. Otherwise, tell the `mys3ql` command where the config file is with the `--config=FILE` switch.
57
62
 
@@ -76,20 +81,8 @@ N.B. the binary logs contain updates to all the databases on the server. This m
76
81
  Marc-André Cournoyer's [mysql_s3_backup](https://github.com/macournoyer/mysql_s3_backup).
77
82
 
78
83
 
79
- ## To Do
80
-
81
- - tests ;)
82
- - remove old dump files (s3)
83
- - (restore from non-latest dump)
84
-
85
-
86
- ## Questions, Problems, Feedback
87
-
88
- Please use the GitHub [issue tracker](https://github.com/airblade/mys3ql/issues) or email me.
89
-
90
-
91
84
  ## Intellectual property
92
85
 
93
- Copyright 2011 Andy Stewart (boss@airbladesoftware.com).
86
+ Copyright 2011-2021 Andy Stewart (boss@airbladesoftware.com).
94
87
 
95
88
  Released under the MIT licence.
data/bin/mys3ql CHANGED
@@ -1,35 +1,26 @@
1
- #!/usr/bin/env ruby-local-exec
2
-
3
- lib_dir = File.join(File.dirname(__FILE__), '..', 'lib')
4
- $LOAD_PATH.unshift lib_dir if File.directory?(lib_dir)
1
+ #!/usr/bin/env ruby
5
2
 
3
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
6
4
  require 'mys3ql'
7
- require 'main'
8
-
9
- Main do
10
- # consider using modes as/when we need command-specific arguments (e.g. restore specific backup)
11
- argument 'command' do
12
- validate { |command| %w[ full incremental restore ].include? command }
13
- description 'specifies the operation to perform [full | incremental | restore]'
14
- end
5
+ require 'optparse'
15
6
 
16
- option 'config', 'c' do
17
- argument :required
18
- description 'load configuration from YAML file'
19
- defaults '~/.mys3ql'
20
- end
7
+ params = {}
8
+ op = OptionParser.new do |opts|
9
+ opts.banner = 'Usage: mys3ql <full|incremental|restore> <[args]>'
21
10
 
22
- option 'debug', 'd' do
23
- description 'be verbose'
11
+ opts.on '-c', '--config CONFIG', 'Load configuration from YAML file (default ~/.mys3ql)'
12
+ opts.on_tail '-d', '--debug', 'Be verbose'
13
+ opts.on_tail '-v', '--version', 'Print version' do
14
+ puts "mys3ql v#{Mys3ql::VERSION}"
15
+ exit
24
16
  end
17
+ end
18
+ op.parse!(into: params)
25
19
 
26
- option 'version', 'v'
27
-
28
- def run
29
- if params[:version].given?
30
- puts "mys3ql v#{Mys3ql::VERSION}"
31
- exit
32
- end
33
- Mys3ql::Conductor.run params[:command].value, params[:config].value, params[:debug].given?
34
- end
20
+ params[:command] = ARGV[0]
21
+ unless %w[full incremental restore].include? params[:command]
22
+ puts op.help
23
+ exit 1
35
24
  end
25
+
26
+ Mys3ql::Conductor.run params[:command], params[:config], params[:debug]
@@ -18,6 +18,10 @@ module Mys3ql
18
18
  @s3 = S3.new @config
19
19
  end
20
20
 
21
+ # Dumps the database and uploads it to S3.
22
+ # Copies the uploaded file to the key :latest.
23
+ # Deletes binary logs from the file system.
24
+ # Deletes binary logs from S3.
21
25
  def full
22
26
  @mysql.dump
23
27
  @s3.store @mysql.dump_file
@@ -25,13 +29,18 @@ module Mys3ql
25
29
  @s3.delete_bin_logs
26
30
  end
27
31
 
32
+ # Uploads mysql's binary logs to S3.
33
+ # The binary logs are left on the file system.
34
+ # Log files already on S3 are not re-uploaded.
28
35
  def incremental
29
36
  @mysql.each_bin_log do |log|
30
37
  @s3.store log, false
31
38
  end
32
39
  end
33
40
 
34
- # for now only restore from latest
41
+ # Downloads the latest dump from S3 and loads it into the database.
42
+ # Downloads each binary log from S3 and loads it into the database.
43
+ # Downloaded files are removed from the file system.
35
44
  def restore
36
45
  # get latest dump
37
46
  with_temp_file do |file|
@@ -48,7 +57,7 @@ module Mys3ql
48
57
  end
49
58
 
50
59
  # NOTE: not sure about this:
51
- puts "You might want to flush mysql's logs..."
60
+ # puts "You might want to flush mysql's logs..."
52
61
  end
53
62
 
54
63
  def debug=(val)
data/lib/mys3ql/config.rb CHANGED
@@ -63,6 +63,10 @@ module Mys3ql
63
63
  s3['bucket']
64
64
  end
65
65
 
66
+ def region
67
+ s3['region']
68
+ end
69
+
66
70
  private
67
71
 
68
72
  def mysql
data/lib/mys3ql/mysql.rb CHANGED
@@ -13,8 +13,10 @@ module Mys3ql
13
13
  #
14
14
 
15
15
  def dump
16
+ # --master-data=2 include the current binary log coordinates in the log file
17
+ # --delete-master-logs delete binary log files
16
18
  cmd = "#{@config.bin_path}mysqldump"
17
- cmd += ' --quick --single-transaction --create-options'
19
+ cmd += ' --quick --single-transaction --create-options --no-tablespaces'
18
20
  cmd += ' --flush-logs --master-data=2 --delete-master-logs' if binary_logging?
19
21
  cmd += cli_options
20
22
  cmd += " | gzip > #{dump_file}"
@@ -36,14 +38,18 @@ module Mys3ql
36
38
 
37
39
  # flushes logs, yields each bar the last to the block
38
40
  def each_bin_log(&block)
41
+ # FLUSH LOGS Closes and reopens any log file, including binary logs,
42
+ # to which the server is writing. For binary logs, the sequence
43
+ # number of the binary log file is incremented by one relative to
44
+ # the previous file.
45
+ # https://dev.mysql.com/doc/refman/5.7/en/flush.html#flush-logs
46
+ # https://dev.mysql.com/doc/refman/5.7/en/flush.html#flush-binary-logs
39
47
  execute 'flush logs'
40
48
  logs = Dir.glob("#{@config.bin_log}.[0-9]*").sort_by { |f| f[/\d+/].to_i }
41
- logs_to_backup = logs[0..-2] # all logs except the last, which is in use
49
+ logs_to_backup = logs[0..-2] # all logs except the last, which is newly created
42
50
  logs_to_backup.each do |log_file|
43
51
  yield log_file
44
52
  end
45
- # delete binlogs from file system
46
- #execute "purge master logs to '#{File.basename(logs[-1])}'"
47
53
  end
48
54
 
49
55
  #
data/lib/mys3ql/s3.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'mys3ql/shell'
2
- require 'fog'
2
+ require 'awd-sdk-s3'
3
3
 
4
4
  module Mys3ql
5
5
  class S3
@@ -7,7 +7,6 @@ module Mys3ql
7
7
 
8
8
  def initialize(config)
9
9
  @config = config
10
- Fog::Logger[:warning] = nil
11
10
  end
12
11
 
13
12
  def store(file, dump = true)
@@ -15,20 +14,22 @@ module Mys3ql
15
14
  s3_file = save file, key
16
15
  if dump && s3_file
17
16
  copy_key = key_for :latest
18
- s3_file.copy @config.bucket, copy_key
17
+ s3_file.copy_to key: copy_key
19
18
  log "s3: copied #{key} to #{copy_key}"
20
19
  end
21
20
  end
22
21
 
23
22
  def delete_bin_logs
24
23
  each_bin_log do |file|
25
- file.destroy
24
+ file.delete
26
25
  log "s3: deleted #{file.key}"
27
26
  end
28
27
  end
29
28
 
30
29
  def each_bin_log(&block)
31
- bucket.files.all(:prefix => "#{bin_logs_prefix}").sort_by { |file| file.key[/\d+/].to_i }.each do |file|
30
+ bucket.objects(prefix: bin_logs_prefix)
31
+ .sort_by { |file| file.key[/\d+/].to_i }
32
+ .each do |file|
32
33
  yield file
33
34
  end
34
35
  end
@@ -41,24 +42,28 @@ module Mys3ql
41
42
  private
42
43
 
43
44
  def get(s3_key, local_file_name)
44
- s3_file = bucket.files.get s3_key
45
- File.open(local_file_name, 'wb') do |file|
46
- file.write s3_file.body
47
- end
45
+ s3.get_object(
46
+ response_target: local_file_name,
47
+ bucket: @config.bucket,
48
+ key: s3_key
49
+ )
48
50
  log "s3: pulled #{s3_key} to #{local_file_name}"
49
51
  end
50
52
 
51
- # returns Fog::Storage::AWS::File if we pushed, nil otherwise.
52
53
  def save(local_file_name, s3_key)
53
- unless bucket.files.head(s3_key)
54
- s3_file = bucket.files.create(
55
- :key => s3_key,
56
- :body => File.open(local_file_name),
57
- :public => false
58
- )
59
- log "s3: pushed #{local_file_name} to #{s3_key}"
60
- s3_file
54
+ if bucket.object(s3_key).exists?
55
+ log "s3: skipped #{local_file_name} - #{s3_key} exists"
56
+ return
61
57
  end
58
+
59
+ s3_file = bucket.put_object(
60
+ key: s3_key,
61
+ body: File.open(local_file_name),
62
+ storage_class: 'STANDARD_IA',
63
+ acl: 'private'
64
+ )
65
+ log "s3: pushed #{local_file_name} to #{s3_key}"
66
+ s3_file
62
67
  end
63
68
 
64
69
  def key_for(kind, file = nil)
@@ -72,22 +77,22 @@ module Mys3ql
72
77
 
73
78
  def s3
74
79
  @s3 ||= begin
75
- s = Fog::Storage.new(
76
- :provider => 'AWS',
77
- :aws_secret_access_key => @config.secret_access_key,
78
- :aws_access_key_id => @config.access_key_id
80
+ client = Aws::S3::Client.new(
81
+ secret_access_key: @config.secret_access_key,
82
+ access_key_id: @config.access_key_id,
83
+ region: @config.region
79
84
  )
80
85
  log 's3: connected'
81
- s
86
+ client
82
87
  end
83
88
  end
84
89
 
85
90
  def bucket
86
- @directory ||= begin
87
- d = s3.directories.get @config.bucket
88
- raise "S3 bucket #{@config.bucket} not found" unless d # create bucket instead?
91
+ @bucket ||= begin
92
+ b = Aws::S3::Bucket.new @config.bucket, client: s3
93
+ raise "S3 bucket #{@config.bucket} not found" unless b.exists?
89
94
  log "s3: opened bucket #{@config.bucket}"
90
- d
95
+ b
91
96
  end
92
97
  end
93
98
 
@@ -102,6 +107,5 @@ module Mys3ql
102
107
  def bin_logs_exist?
103
108
  @config.bin_log && @config.bin_log.length > 0 && File.exist?(@config.bin_log)
104
109
  end
105
-
106
110
  end
107
111
  end
data/lib/mys3ql/shell.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Mys3ql
2
- class ShellCommandError < RuntimeError ; end
2
+ ShellCommandError = Class.new RuntimeError
3
3
 
4
4
  module Shell
5
5
  def run(command)
@@ -1,3 +1,3 @@
1
1
  module Mys3ql
2
- VERSION = '1.0.0'
2
+ VERSION = '1.2.0'
3
3
  end
data/mys3ql.gemspec CHANGED
@@ -11,14 +11,11 @@ Gem::Specification.new do |s|
11
11
  s.summary = 'Simple backup of your MySql database onto Amazon S3.'
12
12
  s.description = s.summary
13
13
 
14
- s.rubyforge_project = "mys3ql"
15
-
16
14
  s.files = `git ls-files`.split("\n")
17
15
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
16
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
17
  s.require_paths = ["lib"]
20
18
 
21
- s.add_dependency 'main', '~> 4.8.0'
22
- s.add_dependency 'fog', '~> 1.0.0'
19
+ s.add_dependency 'aws-sdk-s3', '~> 1'
23
20
  s.add_development_dependency 'rake'
24
21
  end
metadata CHANGED
@@ -1,81 +1,52 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: mys3ql
3
- version: !ruby/object:Gem::Version
4
- hash: 23
5
- prerelease:
6
- segments:
7
- - 1
8
- - 0
9
- - 0
10
- version: 1.0.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.0
11
5
  platform: ruby
12
- authors:
6
+ authors:
13
7
  - Andy Stewart
14
- autorequire:
8
+ autorequire:
15
9
  bindir: bin
16
10
  cert_chain: []
17
-
18
- date: 2011-11-04 00:00:00 +01:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
22
- name: main
23
- prerelease: false
24
- version_requirements: &id001 !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ~>
28
- - !ruby/object:Gem::Version
29
- hash: 31
30
- segments:
31
- - 4
32
- - 8
33
- - 0
34
- version: 4.8.0
11
+ date: 2021-02-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: aws-sdk-s3
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1'
35
20
  type: :runtime
36
- requirement: *id001
37
- - !ruby/object:Gem::Dependency
38
- name: fog
39
21
  prerelease: false
40
- version_requirements: &id002 !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ~>
44
- - !ruby/object:Gem::Version
45
- hash: 23
46
- segments:
47
- - 1
48
- - 0
49
- - 0
50
- version: 1.0.0
51
- type: :runtime
52
- requirement: *id002
53
- - !ruby/object:Gem::Dependency
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1'
27
+ - !ruby/object:Gem::Dependency
54
28
  name: rake
55
- prerelease: false
56
- version_requirements: &id003 !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
59
31
  - - ">="
60
- - !ruby/object:Gem::Version
61
- hash: 3
62
- segments:
63
- - 0
64
- version: "0"
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
65
34
  type: :development
66
- requirement: *id003
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
67
41
  description: Simple backup of your MySql database onto Amazon S3.
68
- email:
42
+ email:
69
43
  - boss@airbladesoftware.com
70
- executables:
44
+ executables:
71
45
  - mys3ql
72
46
  extensions: []
73
-
74
47
  extra_rdoc_files: []
75
-
76
- files:
77
- - .gitignore
78
- - CHANGELOG.md
48
+ files:
49
+ - ".gitignore"
79
50
  - Gemfile
80
51
  - README.md
81
52
  - Rakefile
@@ -88,39 +59,26 @@ files:
88
59
  - lib/mys3ql/shell.rb
89
60
  - lib/mys3ql/version.rb
90
61
  - mys3ql.gemspec
91
- has_rdoc: true
92
62
  homepage: https://github.com/airblade/mys3ql
93
63
  licenses: []
94
-
95
- post_install_message:
64
+ metadata: {}
65
+ post_install_message:
96
66
  rdoc_options: []
97
-
98
- require_paths:
67
+ require_paths:
99
68
  - lib
100
- required_ruby_version: !ruby/object:Gem::Requirement
101
- none: false
102
- requirements:
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
103
71
  - - ">="
104
- - !ruby/object:Gem::Version
105
- hash: 3
106
- segments:
107
- - 0
108
- version: "0"
109
- required_rubygems_version: !ruby/object:Gem::Requirement
110
- none: false
111
- requirements:
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
112
76
  - - ">="
113
- - !ruby/object:Gem::Version
114
- hash: 3
115
- segments:
116
- - 0
117
- version: "0"
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
118
79
  requirements: []
119
-
120
- rubyforge_project: mys3ql
121
- rubygems_version: 1.6.2
122
- signing_key:
123
- specification_version: 3
80
+ rubygems_version: 3.1.2
81
+ signing_key:
82
+ specification_version: 4
124
83
  summary: Simple backup of your MySql database onto Amazon S3.
125
84
  test_files: []
126
-
data/CHANGELOG.md DELETED
@@ -1,3 +0,0 @@
1
- # Changelog
2
-
3
- [awaiting v1.0.0]