wp_backup 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|