backup 3.2.0 → 3.3.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.
@@ -28,33 +28,16 @@ module Backup
28
28
  # Additional "pg_dump" options
29
29
  attr_accessor :additional_options
30
30
 
31
- ##
32
- # Path to pg_dump utility (optional)
33
- attr_accessor :pg_dump_utility
34
-
35
- attr_deprecate :utility_path, :version => '3.0.21',
36
- :message => 'Use PostgreSQL#pg_dump_utility instead.',
37
- :action => lambda {|klass, val| klass.pg_dump_utility = val }
38
-
39
- ##
40
- # Creates a new instance of the PostgreSQL adapter object
41
- # Sets the PGPASSWORD environment variable to the password
42
- # so it doesn't prompt and hang in the process
43
- def initialize(model, &block)
44
- super(model)
45
-
46
- @skip_tables ||= Array.new
47
- @only_tables ||= Array.new
48
- @additional_options ||= Array.new
49
-
31
+ def initialize(model, database_id = nil, &block)
32
+ super
50
33
  instance_eval(&block) if block_given?
51
-
52
- @pg_dump_utility ||= utility(:pg_dump)
53
34
  end
54
35
 
55
36
  ##
56
- # Performs the pgdump command and outputs the
57
- # data to the specified path based on the 'trigger'
37
+ # Performs the mysqldump command and outputs the dump file
38
+ # in the +dump_path+ using +dump_filename+.
39
+ #
40
+ # <trigger>/databases/PostgreSQL[-<database_id>].sql[.gz]
58
41
  def perform!
59
42
  super
60
43
 
@@ -62,84 +45,75 @@ module Backup
62
45
  dump_ext = 'sql'
63
46
 
64
47
  pipeline << pgdump
65
- if @model.compressor
66
- @model.compressor.compress_with do |command, ext|
67
- pipeline << command
68
- dump_ext << ext
69
- end
70
- end
48
+
49
+ model.compressor.compress_with do |command, ext|
50
+ pipeline << command
51
+ dump_ext << ext
52
+ end if model.compressor
71
53
 
72
54
  pipeline << "#{ utility(:cat) } > " +
73
- "'#{ File.join(@dump_path, name) }.#{ dump_ext }'"
55
+ "'#{ File.join(dump_path, dump_filename) }.#{ dump_ext }'"
56
+
74
57
  pipeline.run
75
58
  if pipeline.success?
76
- Logger.info "#{ database_name } Complete!"
59
+ log!(:finished)
77
60
  else
78
61
  raise Errors::Database::PipelineError,
79
- "#{ database_name } Dump Failed!\n" +
80
- pipeline.error_messages
62
+ "#{ database_name } Dump Failed!\n" + pipeline.error_messages
81
63
  end
82
64
  end
83
65
 
84
- ##
85
- # Builds the full pgdump string based on all attributes
86
66
  def pgdump
87
- "#{password_options}" +
88
- "#{ pg_dump_utility } #{ username_options } #{ connectivity_options } " +
67
+ "#{ password_option }" +
68
+ "#{ utility(:pg_dump) } #{ username_option } #{ connectivity_options } " +
89
69
  "#{ user_options } #{ tables_to_dump } #{ tables_to_skip } #{ name }"
90
70
  end
91
71
 
92
- ##
93
- # Builds the password syntax PostgreSQL uses to authenticate the user
94
- # to perform database dumping
95
- def password_options
96
- password.to_s.empty? ? '' : "PGPASSWORD='#{password}' "
72
+ def password_option
73
+ "PGPASSWORD='#{ password }' " if password
97
74
  end
98
75
 
99
- ##
100
- # Builds the credentials PostgreSQL syntax to authenticate the user
101
- # to perform the database dumping process
102
- def username_options
103
- username.to_s.empty? ? '' : "--username='#{username}'"
76
+ def username_option
77
+ "--username='#{ username }'" if username
104
78
  end
105
79
 
106
- ##
107
- # Builds the PostgreSQL connectivity options syntax to connect the user
108
- # to perform the database dumping process, socket gets gsub'd to host since
109
- # that's the option PostgreSQL takes for socket connections as well. In case
110
- # both the host and the socket are specified, the socket will take priority over the host
111
80
  def connectivity_options
112
- %w[host port socket].map do |option|
113
- next if send(option).to_s.empty?
114
- "--#{option}='#{send(option)}'".gsub('--socket=', '--host=')
115
- end.compact.join(' ')
81
+ return "--host='#{ socket }'" if socket
82
+
83
+ opts = []
84
+ opts << "--host='#{ host }'" if host
85
+ opts << "--port='#{ port }'" if port
86
+ opts.join(' ')
116
87
  end
117
88
 
118
- ##
119
- # Builds a PostgreSQL compatible string for the additional options
120
- # specified by the user
121
89
  def user_options
122
- additional_options.join(' ')
90
+ Array(additional_options).join(' ')
123
91
  end
124
92
 
125
- ##
126
- # Builds the PostgreSQL syntax for specifying which tables to dump
127
- # during the dumping of the database
128
93
  def tables_to_dump
129
- only_tables.map do |table|
130
- "--table='#{table}'"
94
+ Array(only_tables).map do |table|
95
+ "--table='#{ table }'"
131
96
  end.join(' ')
132
97
  end
133
98
 
134
- ##
135
- # Builds the PostgreSQL syntax for specifying which tables to skip
136
- # during the dumping of the database
137
99
  def tables_to_skip
138
- skip_tables.map do |table|
139
- "--exclude-table='#{table}'"
100
+ Array(skip_tables).map do |table|
101
+ "--exclude-table='#{ table }'"
140
102
  end.join(' ')
141
103
  end
142
104
 
105
+ attr_deprecate :utility_path, :version => '3.0.21',
106
+ :message => 'Use Backup::Utilities.configure instead.',
107
+ :action => lambda {|klass, val|
108
+ Utilities.configure { pg_dump val }
109
+ }
110
+
111
+ attr_deprecate :pg_dump_utility, :version => '3.3.0',
112
+ :message => 'Use Backup::Utilities.configure instead.',
113
+ :action => lambda {|klass, val|
114
+ Utilities.configure { pg_dump val }
115
+ }
116
+
143
117
  end
144
118
  end
145
119
  end
@@ -5,85 +5,76 @@ module Backup
5
5
  class Redis < Base
6
6
 
7
7
  ##
8
- # Name of and path to the database that needs to get dumped
9
- attr_accessor :name, :path
8
+ # Name of the redis dump file.
9
+ #
10
+ # This is set in `redis.conf` as `dbfilename`.
11
+ # This must be set to the name of that file without the `.rdb` extension.
12
+ # Default: 'dump'
13
+ attr_accessor :name
10
14
 
11
15
  ##
12
- # Credentials for the specified database
16
+ # Path to the redis dump file.
17
+ #
18
+ # This is set in `redis.conf` as `dir`.
19
+ attr_accessor :path
20
+
21
+ ##
22
+ # Password for the redis-cli utility to perform the `SAVE` command
23
+ # if +invoke_save+ is set `true`.
13
24
  attr_accessor :password
14
25
 
15
26
  ##
16
- # Connectivity options
27
+ # Connectivity options for the +invoke_save+ option.
17
28
  attr_accessor :host, :port, :socket
18
29
 
19
30
  ##
20
- # Determines whether Backup should invoke the SAVE command through
21
- # the 'redis-cli' utility to persist the most recent data before
22
- # copying over the dump file
31
+ # Determines whether Backup should invoke the `SAVE` command through
32
+ # the `redis-cli` utility to persist the most recent data before
33
+ # copying the dump file specified by +path+ and +name+.
23
34
  attr_accessor :invoke_save
24
35
 
25
36
  ##
26
37
  # Additional "redis-cli" options
27
38
  attr_accessor :additional_options
28
39
 
29
- ##
30
- # Path to the redis-cli utility (optional)
31
- attr_accessor :redis_cli_utility
32
-
33
- attr_deprecate :utility_path, :version => '3.0.21',
34
- :message => 'Use Redis#redis_cli_utility instead.',
35
- :action => lambda {|klass, val| klass.redis_cli_utility = val }
36
-
37
- ##
38
- # Creates a new instance of the Redis database object
39
- def initialize(model, &block)
40
- super(model)
41
-
42
- @additional_options ||= Array.new
43
-
40
+ def initialize(model, database_id = nil, &block)
41
+ super
44
42
  instance_eval(&block) if block_given?
45
43
 
46
44
  @name ||= 'dump'
47
- @redis_cli_utility ||= utility('redis-cli')
48
45
  end
49
46
 
50
47
  ##
51
- # Performs the Redis backup by using the 'cp' unix utility
52
- # to copy the persisted Redis dump file to the Backup archive.
53
- # Additionally, when 'invoke_save' is set to true, it'll tell
54
- # the Redis server to persist the current state to the dump file
55
- # before copying the dump to get the most recent updates in to the backup
48
+ # Copies and optionally compresses the Redis dump file to the
49
+ # +dump_path+ using the +dump_filename+.
50
+ #
51
+ # <trigger>/databases/Redis[-<database_id>].rdb[.gz]
52
+ #
53
+ # If +invoke_save+ is true, `redis-cli SAVE` will be invoked.
56
54
  def perform!
57
55
  super
58
56
 
59
57
  invoke_save! if invoke_save
60
58
  copy!
59
+
60
+ log!(:finished)
61
61
  end
62
62
 
63
63
  private
64
64
 
65
- ##
66
- # Tells Redis to persist the current state of the
67
- # in-memory database to the persisted dump file
68
65
  def invoke_save!
69
- response = run("#{ redis_cli_utility } #{ credential_options } " +
70
- "#{ connectivity_options } #{ user_options } SAVE")
71
- unless response =~ /OK/
66
+ resp = run(redis_save_cmd)
67
+ unless resp =~ /OK$/
72
68
  raise Errors::Database::Redis::CommandError, <<-EOS
73
69
  Could not invoke the Redis SAVE command.
74
- The #{ database } file might not contain the most recent data.
75
- Please check if the server is running, the credentials (if any) are correct,
76
- and the host/port/socket are correct.
77
-
78
- Redis CLI response: #{ response }
70
+ Command was: #{ redis_save_cmd }
71
+ Response was: #{ resp }
79
72
  EOS
80
73
  end
81
74
  end
82
75
 
83
- ##
84
- # Performs the copy command to copy over the Redis dump file to the Backup archive
85
76
  def copy!
86
- src_path = File.join(path, database)
77
+ src_path = File.join(path, name + '.rdb')
87
78
  unless File.exist?(src_path)
88
79
  raise Errors::Database::Redis::NotFoundError, <<-EOS
89
80
  Redis database dump not found
@@ -91,46 +82,50 @@ module Backup
91
82
  EOS
92
83
  end
93
84
 
94
- dst_path = File.join(@dump_path, database)
95
- if @model.compressor
96
- @model.compressor.compress_with do |command, ext|
97
- run("#{ command } -c #{ src_path } > #{ dst_path + ext }")
85
+ dst_path = File.join(dump_path, dump_filename + '.rdb')
86
+ if model.compressor
87
+ model.compressor.compress_with do |command, ext|
88
+ run("#{ command } -c '#{ src_path }' > '#{ dst_path + ext }'")
98
89
  end
99
90
  else
100
91
  FileUtils.cp(src_path, dst_path)
101
92
  end
102
93
  end
103
94
 
104
- ##
105
- # Returns the Redis database file name
106
- def database
107
- "#{ name }.rdb"
95
+ def redis_save_cmd
96
+ "#{ utility('redis-cli') } #{ password_option } " +
97
+ "#{ connectivity_options } #{ user_options } SAVE"
108
98
  end
109
99
 
110
- ##
111
- # Builds the Redis credentials syntax to authenticate the user
112
- # to perform the database dumping process
113
- def credential_options
114
- password.to_s.empty? ? '' : "-a '#{password}'"
100
+ def password_option
101
+ "-a '#{ password }'" if password
115
102
  end
116
103
 
117
- ##
118
- # Builds the Redis connectivity options syntax to connect the user
119
- # to perform the database dumping process
120
104
  def connectivity_options
121
- %w[host port socket].map do |option|
122
- next if send(option).to_s.empty?
123
- "-#{option[0,1]} '#{send(option)}'"
124
- end.compact.join(' ')
105
+ return "-s '#{ socket }'" if socket
106
+
107
+ opts = []
108
+ opts << "-h '#{ host }'" if host
109
+ opts << "-p '#{ port }'" if port
110
+ opts.join(' ')
125
111
  end
126
112
 
127
- ##
128
- # Builds a Redis compatible string for the
129
- # additional options specified by the user
130
113
  def user_options
131
- @additional_options.join(' ')
114
+ Array(additional_options).join(' ')
132
115
  end
133
116
 
117
+ attr_deprecate :utility_path, :version => '3.0.21',
118
+ :message => 'Use Backup::Utilities.configure instead.',
119
+ :action => lambda {|klass, val|
120
+ Utilities.configure { redis_cli val }
121
+ }
122
+
123
+ attr_deprecate :redis_cli_utility, :version => '3.3.0',
124
+ :message => 'Use Backup::Utilities.configure instead.',
125
+ :action => lambda {|klass, val|
126
+ Utilities.configure { redis_cli val }
127
+ }
128
+
134
129
  end
135
130
  end
136
131
  end
@@ -4,77 +4,98 @@ module Backup
4
4
  module Database
5
5
  class Riak < Base
6
6
 
7
- ##
8
- # Name is the name of the backup
9
- attr_accessor :name
10
-
11
7
  ##
12
8
  # Node is the node from which to perform the backup.
9
+ # Default: riak@127.0.0.1
13
10
  attr_accessor :node
14
11
 
15
12
  ##
16
13
  # Cookie is the Erlang cookie/shared secret used to connect to the node.
14
+ # Default: riak
17
15
  attr_accessor :cookie
18
16
 
19
17
  ##
20
- # Path to riak-admin utility (optional)
21
- attr_accessor :riak_admin_utility
22
-
23
- ##
24
- # Username for the riak instance (optional)
18
+ # Username for the riak instance
19
+ # Default: riak
25
20
  attr_accessor :user
26
21
 
27
- ##
28
- # Group for the riak instance (optional)
29
- attr_accessor :group
30
-
31
- attr_deprecate :utility_path, :version => '3.0.21',
32
- :message => 'Use Riak#riak_admin_utility instead.',
33
- :action => lambda {|klass, val| klass.riak_admin_utility = val }
34
-
35
- ##
36
- # Creates a new instance of the Riak adapter object
37
- def initialize(model, &block)
38
- super(model)
39
-
22
+ def initialize(model, database_id = nil, &block)
23
+ super
40
24
  instance_eval(&block) if block_given?
41
25
 
42
- @riak_admin_utility ||= utility('riak-admin')
43
- @user ||= 'riak'
44
- @group ||= 'riak'
26
+ @node ||= 'riak@127.0.0.1'
27
+ @cookie ||= 'riak'
28
+ @user ||= 'riak'
45
29
  end
46
30
 
47
31
  ##
48
- # Performs the `riak-admin` command which creates a single dump file in
49
- # @dump_path based on the `name` and `node`.
32
+ # Performs the dump using `riak-admin backup`.
50
33
  #
51
- # `riak-admin` will append the `node` to the filename.
52
- # i.e. <tmp_path>/<trigger>/databases/Riak/<name>-<node>
34
+ # This will be stored in the final backup package as
35
+ # <trigger>/databases/<dump_filename>-<node>[.gz]
53
36
  def perform!
54
37
  super
55
- # ensure riak-admin user has permissions to write backup file
56
- FileUtils.chown_R(@user, @group, @dump_path)
57
-
58
- backup_file = File.join(@dump_path, name)
59
- run("#{ riakadmin } #{ backup_file } node")
60
-
61
- if @model.compressor
62
- @model.compressor.compress_with do |command, ext|
63
- backup_file << "-#{ node }"
64
- run("#{ command } -c #{ backup_file } > #{ backup_file + ext }")
65
- FileUtils.rm_f(backup_file)
66
- end
38
+
39
+ dump_file = File.join(dump_path, dump_filename)
40
+ with_riak_owned_dump_path do
41
+ run("#{ riakadmin } backup #{ node } #{ cookie } '#{ dump_file }' node")
67
42
  end
43
+
44
+ model.compressor.compress_with do |command, ext|
45
+ dump_file << "-#{ node }" # `riak-admin` appends `node` to the filename.
46
+ run("#{ command } -c '#{ dump_file }' > '#{ dump_file + ext }'")
47
+ FileUtils.rm_f(dump_file)
48
+ end if model.compressor
49
+
50
+ log!(:finished)
68
51
  end
69
52
 
70
53
  private
71
54
 
72
55
  ##
73
- # Builds the full riak-admin string based on all attributes
56
+ # The `riak-admin backup` command is run as the riak +user+,
57
+ # so +user+ must have write priviledges to the +dump_path+.
58
+ #
59
+ # Note that the riak +user+ must also have access to +dump_path+.
60
+ # This means Backup's +tmp_path+ can not be under the home directory of
61
+ # the user running Backup, since the absence of the execute bit on their
62
+ # home directory would deny +user+ access.
63
+ def with_riak_owned_dump_path
64
+ run("#{ utility(:sudo) } -n #{ utility(:chown) } " +
65
+ "#{ user } '#{ dump_path }'")
66
+ yield
67
+ ensure
68
+ # reclaim ownership
69
+ run("#{ utility(:sudo) } -n #{ utility(:chown) } -R " +
70
+ "#{ Config.user } '#{ dump_path }'")
71
+ end
72
+
73
+ ##
74
+ # `riak-admin` must be run as the riak +user+.
75
+ # It will do this itself, but without `-n` and emits a message on STDERR.
74
76
  def riakadmin
75
- "#{ riak_admin_utility } backup #{ node } #{ cookie }"
77
+ "#{ utility(:sudo) } -n -u #{ user } #{ utility('riak-admin') }"
76
78
  end
77
79
 
80
+ attr_deprecate :utility_path, :version => '3.0.21',
81
+ :message => 'Use Backup::Utilities.configure instead.',
82
+ :action => lambda {|klass, val|
83
+ Utilities.configure { riak_admin val }
84
+ }
85
+
86
+ attr_deprecate :riak_admin_utility, :version => '3.3.0',
87
+ :message => 'Use Backup::Utilities.configure instead.',
88
+ :action => lambda {|klass, val|
89
+ Utilities.configure { riak_admin val }
90
+ }
91
+
92
+ attr_deprecate :name, :version => '3.3.0',
93
+ :message => "If you wish to add an identifier to the dump filename,\n" +
94
+ "use a +database_id+ when defining the database in your Model.\n" +
95
+ "e.g. database Riak, :my_id do |db|"
96
+
97
+ attr_deprecate :group, :version => '3.3.0'
98
+
78
99
  end
79
100
  end
80
101
  end