wp_backup 0.1.1
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.
- data/.gitignore +1 -0
- data/LICENSE +22 -0
- data/README.md +20 -0
- data/Rakefile +16 -0
- data/bin/wp_backup +23 -0
- data/lib/wp_backup/backup.rb +56 -0
- data/lib/wp_backup/cli.rb +50 -0
- data/lib/wp_backup/config.rb +67 -0
- data/lib/wp_backup/database.rb +27 -0
- data/lib/wp_backup/s3.rb +42 -0
- data/lib/wp_backup/site.rb +20 -0
- data/lib/wp_backup/version.rb +3 -0
- data/lib/wp_backup.rb +8 -0
- data/sample.rb +193 -0
- data/spec/LICENSE +22 -0
- data/spec/README.md +29 -0
- data/spec/Rakefile +16 -0
- data/wp_backup.gemspec +33 -0
- metadata +111 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.gem
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Aubrey Holland
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# WpBackup
|
2
|
+
|
3
|
+
WpBackup is a simple command-line tool for backing up Wordpress sites and their
|
4
|
+
databases to S3. It uses mysqldump to create a database drop and then copies
|
5
|
+
either the entire site from your wordpress directory or specific paths. The operation
|
6
|
+
is entirely configurable by a simple file.
|
7
|
+
|
8
|
+
## <a name="installation"></a>Installation
|
9
|
+
|
10
|
+
gem install wp_backup
|
11
|
+
|
12
|
+
## <a name="usage"></a>Usage
|
13
|
+
|
14
|
+
You'll now have acceess to the wp_backup command. Try "wp_backup help" to get a list of available tasks.
|
15
|
+
|
16
|
+
## <a name="copyright"></a>Copyright
|
17
|
+
Copyright (c) 2012 Aubrey Holland
|
18
|
+
See [LICENSE][] for details.
|
19
|
+
|
20
|
+
[license]: https://github.com/aub/tumble/blob/master/LICENSE.md
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.unshift File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
task :release => %w(man:clean man:build)
|
5
|
+
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
require 'ronn'
|
8
|
+
|
9
|
+
desc "Run specs"
|
10
|
+
RSpec::Core::RakeTask.new do |t|
|
11
|
+
t.rspec_opts = %w(-fs --color)
|
12
|
+
t.ruby_opts = %w(-w)
|
13
|
+
end
|
14
|
+
task :spec => "man:build"
|
15
|
+
|
16
|
+
task :default => :spec
|
data/bin/wp_backup
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'wp_backup'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'wp_backup/cli'
|
7
|
+
WpBackup::CLI.start
|
8
|
+
rescue WpBackup::BackupError => e
|
9
|
+
puts e.message
|
10
|
+
puts e.backtrace.join("\n")
|
11
|
+
exit e.status_code
|
12
|
+
rescue Interrupt => e
|
13
|
+
puts "\nQuitting..."
|
14
|
+
puts e.backtrace.join("\n")
|
15
|
+
exit 1
|
16
|
+
rescue SystemExit => e
|
17
|
+
exit e.status
|
18
|
+
rescue Exception => e
|
19
|
+
puts 'Fatal Error!'
|
20
|
+
puts e.message
|
21
|
+
puts e.backtrace.join("\n")
|
22
|
+
raise e
|
23
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module WpBackup
|
2
|
+
class Backup
|
3
|
+
|
4
|
+
def initialize(config)
|
5
|
+
@config = config
|
6
|
+
end
|
7
|
+
|
8
|
+
def create(backup_db=true, backup_site=true)
|
9
|
+
timestamp = Time.now.utc.strftime("%Y%m%d%H%M%S")
|
10
|
+
root_dir = "/tmp/wp-backup-#{timestamp}"
|
11
|
+
|
12
|
+
begin
|
13
|
+
if backup_site
|
14
|
+
site_dir = File.join(root_dir, 'site')
|
15
|
+
FileUtils.mkdir_p(site_dir)
|
16
|
+
site_file = @config.site.dump_to(File.join(root_dir, 'site', 'site.tar'))
|
17
|
+
end
|
18
|
+
|
19
|
+
if backup_db
|
20
|
+
db_dir = File.join(root_dir, 'db')
|
21
|
+
FileUtils.mkdir_p(db_dir)
|
22
|
+
db_file = @config.database.dump_to(File.join(db_dir, 'db.sql'))
|
23
|
+
end
|
24
|
+
|
25
|
+
package_file = "/tmp/wp-backup-#{timestamp}.tar.gz"
|
26
|
+
`cd #{root_dir} && tar -czf #{package_file} db site`
|
27
|
+
|
28
|
+
@config.s3.store(package_file)
|
29
|
+
ensure
|
30
|
+
`rm -rf #{root_dir}`
|
31
|
+
end
|
32
|
+
|
33
|
+
timestamp
|
34
|
+
end
|
35
|
+
|
36
|
+
def restore(key)
|
37
|
+
timestamp = Time.now.utc.strftime("%Y%m%d%H%M%S")
|
38
|
+
root_dir = "/tmp/wp-restore-#{timestamp}"
|
39
|
+
|
40
|
+
FileUtils.mkdir_p(root_dir)
|
41
|
+
|
42
|
+
begin
|
43
|
+
File.open(File.join(root_dir, 'restore.tar.gz'), 'w') do |file|
|
44
|
+
file.puts(@config.s3.read(key))
|
45
|
+
end
|
46
|
+
|
47
|
+
`cd #{root_dir} && tar -xzvf restore.tar.gz`
|
48
|
+
|
49
|
+
@config.database.restore_from(File.join(root_dir, 'db', 'db.sql'))
|
50
|
+
@config.site.restore_from(File.join(root_dir, 'site', 'site.tar'))
|
51
|
+
ensure
|
52
|
+
`rm -rf #{root_dir}`
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
module WpBackup
|
4
|
+
class CLI < Thor
|
5
|
+
desc 'backup', 'back up the blog residing in the given directory to S3'
|
6
|
+
method_option :config_file, :aliases => '-c', :desc => 'The location of the configuration file. This is assumed to be wp_backup.yml in the current directory unless given.'
|
7
|
+
method_option :db_only, :aliases => '-d', :desc => 'Only back up the database.'
|
8
|
+
method_option :site_only, :aliases => '-s', :desc => 'Only back up the site.'
|
9
|
+
def backup
|
10
|
+
config = Config.new(options[:config_file])
|
11
|
+
key = Backup.new(config).create(!options[:site_only], !options[:db_only])
|
12
|
+
puts "Backed up to #{key}"
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'list', 'list the currently saved backups'
|
16
|
+
method_option :config_file, :aliases => '-c', :desc => 'The location of the configuration file. This is assumed to be wp_backup.yml in the current directory unless given.'
|
17
|
+
def list
|
18
|
+
config = Config.new(options[:config_file])
|
19
|
+
keys = config.s3.keys
|
20
|
+
puts "Found #{keys.count} versions:"
|
21
|
+
puts "========================"
|
22
|
+
keys.each { |k| puts k }
|
23
|
+
end
|
24
|
+
|
25
|
+
desc 'cleanup', 'delete the least recent n backups'
|
26
|
+
method_option :keep, :aliases => '-k', :desc => 'The number of backups to keep, defaults to 10'
|
27
|
+
method_option :config_file, :aliases => '-c', :desc => 'The location of the configuration file. This is assumed to be wp_backup.yml in the current directory unless given.'
|
28
|
+
def cleanup
|
29
|
+
config = Config.new(options[:config_file])
|
30
|
+
keep = options[:keep]
|
31
|
+
timestamps = {}
|
32
|
+
config.s3.keys.each { |k| timestamps[Time.parse(k, "%Y%m%d%H%M%S")] = k }
|
33
|
+
remove = timestamps.keys.sort.reverse.slice(keep.to_i, timestamps.length)
|
34
|
+
timestamps.keep_if { |k,v| remove.include?(k) }
|
35
|
+
config.s3.delete_keys(timestamps.values)
|
36
|
+
end
|
37
|
+
|
38
|
+
desc 'restore KEY', 'restore from the given backup key. See the List command for the set of available keys.'
|
39
|
+
method_option :config_file, :aliases => '-c', :desc => 'The location of the configuration file. This is assumed to be wp_backup.yml in the current directory unless given.'
|
40
|
+
def restore(key)
|
41
|
+
config = Config.new(options[:config_file])
|
42
|
+
Backup.new(config).restore(key)
|
43
|
+
end
|
44
|
+
|
45
|
+
desc 'create_config file', 'create a sample config file'
|
46
|
+
def create_config(file)
|
47
|
+
Config.write_sample(file)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module WpBackup
|
4
|
+
class Config
|
5
|
+
|
6
|
+
def initialize(file)
|
7
|
+
@config = YAML.load_file(file)
|
8
|
+
@bucket_name = @config['aws'].delete('bucket')
|
9
|
+
end
|
10
|
+
|
11
|
+
def s3
|
12
|
+
S3.new(aws_config, @bucket_name)
|
13
|
+
end
|
14
|
+
|
15
|
+
def database
|
16
|
+
Database.new(
|
17
|
+
database_config['name'],
|
18
|
+
database_config['user'],
|
19
|
+
database_config['password']
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def site
|
24
|
+
Site.new(wordpress_config['home'], wordpress_config['backup_paths'])
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.write_sample(file)
|
28
|
+
File.open(file, 'w') do |file|
|
29
|
+
file.puts(<<-EOF
|
30
|
+
database:
|
31
|
+
name:
|
32
|
+
user:
|
33
|
+
password:
|
34
|
+
wordpress:
|
35
|
+
home:
|
36
|
+
# this allows you to specify which directories to backup. if it's not
|
37
|
+
# included or the list is empty the entire directory is backed up.
|
38
|
+
backup_paths:
|
39
|
+
-
|
40
|
+
aws:
|
41
|
+
access_key_id:
|
42
|
+
secret_access_key:
|
43
|
+
bucket:
|
44
|
+
EOF
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def aws_config
|
52
|
+
@aws_config ||= @config['aws']
|
53
|
+
end
|
54
|
+
|
55
|
+
def database_config
|
56
|
+
@database_config ||= @config['database']
|
57
|
+
end
|
58
|
+
|
59
|
+
def bucket_name
|
60
|
+
@bucket_name
|
61
|
+
end
|
62
|
+
|
63
|
+
def wordpress_config
|
64
|
+
@wordpress_config ||= @config['wordpress']
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module WpBackup
|
2
|
+
class Database
|
3
|
+
|
4
|
+
def initialize(db_name, login, password)
|
5
|
+
@db_name = db_name
|
6
|
+
@login = login
|
7
|
+
@password = password
|
8
|
+
end
|
9
|
+
|
10
|
+
def dump_to(file)
|
11
|
+
cmd = "mysqldump --opt --skip-add-locks -u#{@login} "
|
12
|
+
cmd += "-p'#{@password}' " unless @password.nil? || @password.length == 0
|
13
|
+
cmd += " #{@db_name} > #{file}"
|
14
|
+
result = system(cmd)
|
15
|
+
raise("ERROR: mysqldump failed (#{$?})") unless result
|
16
|
+
end
|
17
|
+
|
18
|
+
def restore_from(file)
|
19
|
+
if File.exists?(file)
|
20
|
+
cmd = "mysql -u#{@login} "
|
21
|
+
cmd += "-p'#{@password}' " unless @password.nil? || @password.length == 0
|
22
|
+
cmd += " #{@db_name} < #{file}"
|
23
|
+
system(cmd)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/wp_backup/s3.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
|
3
|
+
module WpBackup
|
4
|
+
class S3
|
5
|
+
def initialize(aws_config, root_bucket)
|
6
|
+
AWS.config(aws_config)
|
7
|
+
@s3 = AWS::S3.new
|
8
|
+
@root_bucket = root_bucket
|
9
|
+
|
10
|
+
@bucket = @s3.buckets.create(@root_bucket)
|
11
|
+
end
|
12
|
+
|
13
|
+
def store(file_name)
|
14
|
+
basename = File.basename(file_name)
|
15
|
+
object = @bucket.objects[basename]
|
16
|
+
object.write(:file => file_name)
|
17
|
+
end
|
18
|
+
|
19
|
+
def read(key)
|
20
|
+
use_key = "wp-backup-#{key}.tar.gz"
|
21
|
+
@bucket.objects[use_key].read
|
22
|
+
end
|
23
|
+
|
24
|
+
def keys
|
25
|
+
[].tap do |keys|
|
26
|
+
@bucket.objects.each do |obj|
|
27
|
+
if obj.key =~ /wp-backup-(\d+).tar.gz/
|
28
|
+
keys << $1
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete_keys(keys)
|
35
|
+
keys.each do |key|
|
36
|
+
puts "Deleting #{key}"
|
37
|
+
use_key = "wp-backup-#{key}.tar.gz"
|
38
|
+
@bucket.objects[use_key].delete
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module WpBackup
|
2
|
+
class Site
|
3
|
+
|
4
|
+
def initialize(root_dir, backup_paths)
|
5
|
+
@root_dir = root_dir
|
6
|
+
@backup_paths = backup_paths || []
|
7
|
+
end
|
8
|
+
|
9
|
+
def dump_to(file)
|
10
|
+
result = `cd #{@root_dir} && tar -cf #{file} #{@backup_paths.any? ? @backup_paths.join(' ') : '.'}`
|
11
|
+
raise("Copy of site failed (#{$?})") unless result
|
12
|
+
end
|
13
|
+
|
14
|
+
def restore_from(file)
|
15
|
+
if File.exists?(file)
|
16
|
+
`cd #{@root_dir} && tar -xf #{file}`
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/wp_backup.rb
ADDED
data/sample.rb
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
# $ rake -f wordpress.rake -T
|
2
|
+
# rake wordpress:backup # Backup both the WordPress database and site
|
3
|
+
# rake wordpress:backup:db # Backup the WordPress database to S3
|
4
|
+
# rake wordpress:backup:site # Backup the WordPress site to S3
|
5
|
+
# rake wordpress:manage:list # List all your backups
|
6
|
+
# rake wordpress:manage:cleanup # Remove all but the last 10 most recent backups or optionally specify KEEP=5 to keep the last 5
|
7
|
+
# rake wordpress:retrieve # Retrieve the latest WordPress database and site backup from S3 (optionally specify VERSION=file_name)
|
8
|
+
# rake wordpress:retrieve:db # Retrieve the latest WordPress database backup from S3 (optionally specify VERSION=file_name)
|
9
|
+
# rake wordpress:retrieve:site # Retrieve the latest WordPress site backup from S3 (optionally specify VERSION=file_name)
|
10
|
+
DBNAME = "your wordpress database name"
|
11
|
+
DBUSER = "your wordpress database username"
|
12
|
+
DBPASSWORD = "your wordpress database password"
|
13
|
+
PATHTOSITE = "/YOUR/HOME/public_html"
|
14
|
+
S3ACCESSKEYID = "your Amazon S3 access id"
|
15
|
+
S3SECRETKEY = "your Amazon S3 secret key"
|
16
|
+
S3BUCKETNAME = "name_of_your_blog"
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
namespace :wordpress do
|
21
|
+
|
22
|
+
desc "Backup WordPress database and site to Amazon S3"
|
23
|
+
task :backup => [ "wordpress:backup:db", "wordpress:backup:site"]
|
24
|
+
|
25
|
+
namespace :backup do
|
26
|
+
desc "Backup the WordPress database to S3"
|
27
|
+
task :db do
|
28
|
+
s3_connect
|
29
|
+
|
30
|
+
msg "Initiating database backup"
|
31
|
+
make_bucket('db')
|
32
|
+
backup = "/tmp/#{backup_name('db')}"
|
33
|
+
|
34
|
+
msg "Dumping database"
|
35
|
+
cmd = "mysqldump --opt --skip-add-locks -u#{DBUSER} "
|
36
|
+
puts cmd + "... [password filtered]"
|
37
|
+
cmd += " -p'#{DBPASSWORD}' " unless DBPASSWORD.empty?
|
38
|
+
cmd += " #{DBNAME} > #{backup}"
|
39
|
+
result = system(cmd)
|
40
|
+
raise("ERROR: mysqldump failed (#{$?})") unless result
|
41
|
+
|
42
|
+
s3_transmit('db', backup)
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "Backup the WordPress site to S3"
|
46
|
+
task :site do
|
47
|
+
s3_connect
|
48
|
+
|
49
|
+
msg "Initiating site backup"
|
50
|
+
make_bucket('site')
|
51
|
+
backup = "/tmp/#{backup_name('site')}"
|
52
|
+
|
53
|
+
cmd = "cp -rp #{PATHTOSITE} #{backup}"
|
54
|
+
msg "Making copy of site"
|
55
|
+
puts cmd
|
56
|
+
result = system(cmd)
|
57
|
+
raise("Copy of site failed (#{$?})") unless result
|
58
|
+
|
59
|
+
s3_transmit('site', backup)
|
60
|
+
end
|
61
|
+
|
62
|
+
end # end backup namespace
|
63
|
+
|
64
|
+
desc "Retrieve the latest WordPress database and site backup from S3. If you need to specify a specific version, call the individual retrieve tasks."
|
65
|
+
task :retrieve => [ "wordpress:retrieve:db", "wordpress:retrieve:site"]
|
66
|
+
|
67
|
+
namespace :retrieve do
|
68
|
+
desc "Retrieve the latest WordPress database backup from S3 (optionally specify VERSION=file_name)"
|
69
|
+
task :db do
|
70
|
+
retrieve_file 'db', ENV['VERSION']
|
71
|
+
end
|
72
|
+
|
73
|
+
desc "Retrieve the latest WordPress site backup from S3 (optionally specify VERSION=file_name)"
|
74
|
+
task :site do
|
75
|
+
retrieve_file 'site', ENV['VERSION']
|
76
|
+
end
|
77
|
+
|
78
|
+
end #end retrieve namespace
|
79
|
+
|
80
|
+
namespace :manage do
|
81
|
+
desc "Remove all but the last 10 most recent backups or optionally specify KEEP=5 to keep the last 5"
|
82
|
+
task :cleanup do
|
83
|
+
s3_connect
|
84
|
+
keep_num = ENV['KEEP'] ? ENV['KEEP'].to_i : 10
|
85
|
+
puts "Keeping the last #{keep_num}"
|
86
|
+
cleanup_bucket('db', keep_num)
|
87
|
+
cleanup_bucket('site', keep_num)
|
88
|
+
end
|
89
|
+
|
90
|
+
desc "Vist all your WordPress backups"
|
91
|
+
task :list do
|
92
|
+
s3_connect
|
93
|
+
print_bucket 'db'
|
94
|
+
print_bucket 'site'
|
95
|
+
end
|
96
|
+
|
97
|
+
end #end manage namespace
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
# Open a connection to Amazon S3
|
103
|
+
def s3_connect
|
104
|
+
s3 = AWS::S3.new
|
105
|
+
AWS::S3::Base.establish_connection!(:access_key_id => "#{S3ACCESSKEYID}", :secret_access_key => "#{S3SECRETKEY}", :use_ssl => true)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Zip up the files and send to S3
|
109
|
+
def s3_transmit(name, tmp_file)
|
110
|
+
backup = "/tmp/#{backup_name(name)}.tar.gz"
|
111
|
+
|
112
|
+
msg "Building tar backup for #{name}"
|
113
|
+
cmd = "tar -cpzf #{backup} #{tmp_file}"
|
114
|
+
puts cmd
|
115
|
+
system cmd
|
116
|
+
|
117
|
+
msg "Sending #{name} backup to S3"
|
118
|
+
AWS::S3::S3Object.store(backup.split('/').last, open(backup), bucket_name(name), :access => :private)
|
119
|
+
msg "Finished sending #{name} to S3"
|
120
|
+
|
121
|
+
msg "Cleaning up"
|
122
|
+
cmd = "rm -rf #{backup} #{tmp_file}"
|
123
|
+
puts cmd
|
124
|
+
system cmd
|
125
|
+
end
|
126
|
+
|
127
|
+
# Obtain a file from S3
|
128
|
+
def s3_retrieve(bucket, specific_file)
|
129
|
+
msg "Retrieving #{specific_file} from #{bucket} on S3"
|
130
|
+
open(specific_file, 'w') do |file|
|
131
|
+
AWS::S3::S3Object.stream(specific_file, bucket) do |chunk|
|
132
|
+
file.write chunk
|
133
|
+
end
|
134
|
+
end
|
135
|
+
msg "Retrieved #{specific_file} from #{bucket} on S3"
|
136
|
+
end
|
137
|
+
|
138
|
+
def retrieve_file(name, specific_file)
|
139
|
+
s3_connect
|
140
|
+
|
141
|
+
if specific_file
|
142
|
+
if AWS::S3::S3Object.exists?(specific_file, bucket_name(name))
|
143
|
+
s3_retrieve(bucket_name(name), specific_file)
|
144
|
+
else
|
145
|
+
msg "Couldn't find #{specific_file} in #{bucket_name(name)} on S3"
|
146
|
+
end
|
147
|
+
else
|
148
|
+
# Just get the latest backup file
|
149
|
+
objects = AWS::S3::Bucket.objects(bucket_name(name))
|
150
|
+
s3_retrieve(bucket_name(name), objects[objects.size-1].key)
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
# Print all backups in a particular bucket
|
156
|
+
def print_bucket(name)
|
157
|
+
msg "Showing contents of #{bucket_name(name)}"
|
158
|
+
bucket = AWS::S3::Bucket.find(bucket_name(name))
|
159
|
+
bucket.objects.each do |object|
|
160
|
+
size = format("%.2f", object.size.to_f/1048576)
|
161
|
+
puts "Name: #{object.key} (#{size}MB)"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# Remove all but KEEP_NUM objects from a particular bucket
|
166
|
+
def cleanup_bucket(name, keep_num)
|
167
|
+
msg "Cleaning up #{bucket_name(name)} (keeping last #{keep_num})"
|
168
|
+
bucket = AWS::S3::Bucket.find(bucket_name(name))
|
169
|
+
objects = bucket.objects
|
170
|
+
remove = objects.size-keep_num-1
|
171
|
+
objects[0..remove].each do |object|
|
172
|
+
response = object.delete
|
173
|
+
end unless remove < 0
|
174
|
+
end
|
175
|
+
|
176
|
+
def make_bucket(name)
|
177
|
+
AWS::S3::Bucket.create(bucket_name(name))
|
178
|
+
msg "Using bucket #{bucket_name(name)}"
|
179
|
+
end
|
180
|
+
|
181
|
+
def bucket_name(name)
|
182
|
+
"#{S3BUCKETNAME}_#{name}"
|
183
|
+
end
|
184
|
+
|
185
|
+
def backup_name(name)
|
186
|
+
@timestamp ||= Time.now.utc.strftime("%Y%m%d%H%M%S")
|
187
|
+
name.sub('_', '.') + ".#{@timestamp}"
|
188
|
+
end
|
189
|
+
|
190
|
+
def msg(text)
|
191
|
+
puts " -- WordPress backup status: #{text}"
|
192
|
+
end
|
193
|
+
|
data/spec/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Aubrey Holland
|
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.
|
data/spec/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Bundler: a gem to bundle gems
|
2
|
+
|
3
|
+
Bundler is a tool that manages gem dependencies for your ruby application. It
|
4
|
+
takes a gem manifest file and is able to fetch, download, and install the gems
|
5
|
+
and all child dependencies specified in this manifest. It can manage any update
|
6
|
+
to the gem manifest file and update the bundle's gems accordingly. It also lets
|
7
|
+
you run any ruby code in context of the bundle's gem environment.
|
8
|
+
|
9
|
+
### Installation and usage
|
10
|
+
|
11
|
+
See [gembundler.com](http://gembundler.com) for up-to-date installation and usage instructions.
|
12
|
+
|
13
|
+
### Troubleshooting
|
14
|
+
|
15
|
+
For help with common problems, see [ISSUES](https://github.com/carlhuda/bundler/blob/master/ISSUES.md).
|
16
|
+
|
17
|
+
### Development
|
18
|
+
|
19
|
+
To see what has changed in recent versions of bundler, see the [CHANGELOG](https://github.com/carlhuda/bundler/blob/master/CHANGELOG.md).
|
20
|
+
|
21
|
+
The `master` branch contains our current progress towards version 1.1. Because of that, please submit bugfix pull requests against the `1-0-stable` branch.
|
22
|
+
|
23
|
+
### Upgrading from Bundler 0.8 to 0.9 and above
|
24
|
+
|
25
|
+
See [UPGRADING](https://github.com/carlhuda/bundler/blob/master/UPGRADING.md).
|
26
|
+
|
27
|
+
### Other questions
|
28
|
+
|
29
|
+
Feel free to chat with the Bundler core team (and many other users) on IRC in the [#bundler](irc://irc.freenode.net/bundler) channel on Freenode, or via email on the [Bundler mailing list](http://groups.google.com/group/ruby-bundler).
|
data/spec/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.unshift File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
task :release => %w(man:clean man:build)
|
5
|
+
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
require 'ronn'
|
8
|
+
|
9
|
+
desc "Run specs"
|
10
|
+
RSpec::Core::RakeTask.new do |t|
|
11
|
+
t.rspec_opts = %w(-fs --color)
|
12
|
+
t.ruby_opts = %w(-w)
|
13
|
+
end
|
14
|
+
task :spec => "man:build"
|
15
|
+
|
16
|
+
task :default => :spec
|
data/wp_backup.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib/', __FILE__)
|
3
|
+
$:.unshift lib unless $:.include?(lib)
|
4
|
+
|
5
|
+
require 'wp_backup/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = 'wp_backup'
|
9
|
+
s.version = WpBackup::VERSION
|
10
|
+
s.platform = Gem::Platform::RUBY
|
11
|
+
s.authors = ['Aubrey Holland']
|
12
|
+
s.email = ['aubreyholland@gmail.com']
|
13
|
+
s.homepage = 'http://github.com/aub/wp_backup'
|
14
|
+
s.summary = %q{A tool for backing up wordpress blogs to s3}
|
15
|
+
s.description = %q{}
|
16
|
+
|
17
|
+
s.required_ruby_version = '>= 1.8.7'
|
18
|
+
s.required_rubygems_version = '>= 1.3.6'
|
19
|
+
s.rubyforge_project = 'wp_backup'
|
20
|
+
|
21
|
+
s.add_dependency 'aws-sdk', '1.5.2'
|
22
|
+
s.add_dependency 'thor', '0.15.2'
|
23
|
+
s.add_development_dependency 'ronn'
|
24
|
+
s.add_development_dependency 'rspec', '~> 2.0'
|
25
|
+
|
26
|
+
# Man files are required because they are ignored by git
|
27
|
+
man_files = Dir.glob('lib/wp_backup/man/**/*')
|
28
|
+
git_files = `git ls-files`.split("\n") rescue ''
|
29
|
+
s.files = git_files + man_files
|
30
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
31
|
+
s.executables = %w(wp_backup)
|
32
|
+
s.require_paths = %w(lib)
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wp_backup
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Aubrey Holland
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-22 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: aws-sdk
|
16
|
+
requirement: &70285341402020 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - =
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.5.2
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70285341402020
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: thor
|
27
|
+
requirement: &70285341401540 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - =
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.15.2
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70285341401540
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: ronn
|
38
|
+
requirement: &70285341401080 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70285341401080
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rspec
|
49
|
+
requirement: &70285341400220 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70285341400220
|
58
|
+
description: ''
|
59
|
+
email:
|
60
|
+
- aubreyholland@gmail.com
|
61
|
+
executables:
|
62
|
+
- wp_backup
|
63
|
+
extensions: []
|
64
|
+
extra_rdoc_files: []
|
65
|
+
files:
|
66
|
+
- .gitignore
|
67
|
+
- LICENSE
|
68
|
+
- README.md
|
69
|
+
- Rakefile
|
70
|
+
- bin/wp_backup
|
71
|
+
- lib/wp_backup.rb
|
72
|
+
- lib/wp_backup/backup.rb
|
73
|
+
- lib/wp_backup/cli.rb
|
74
|
+
- lib/wp_backup/config.rb
|
75
|
+
- lib/wp_backup/database.rb
|
76
|
+
- lib/wp_backup/s3.rb
|
77
|
+
- lib/wp_backup/site.rb
|
78
|
+
- lib/wp_backup/version.rb
|
79
|
+
- sample.rb
|
80
|
+
- spec/LICENSE
|
81
|
+
- spec/README.md
|
82
|
+
- spec/Rakefile
|
83
|
+
- wp_backup.gemspec
|
84
|
+
homepage: http://github.com/aub/wp_backup
|
85
|
+
licenses: []
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options: []
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: 1.8.7
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 1.3.6
|
102
|
+
requirements: []
|
103
|
+
rubyforge_project: wp_backup
|
104
|
+
rubygems_version: 1.8.10
|
105
|
+
signing_key:
|
106
|
+
specification_version: 3
|
107
|
+
summary: A tool for backing up wordpress blogs to s3
|
108
|
+
test_files:
|
109
|
+
- spec/LICENSE
|
110
|
+
- spec/README.md
|
111
|
+
- spec/Rakefile
|