backup_foundation 0.2.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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +69 -0
- data/Rakefile +2 -0
- data/backup_foundation.gemspec +34 -0
- data/lib/backup_foundation.rb +32 -0
- data/lib/backup_foundation/capistrano.rb +7 -0
- data/lib/backup_foundation/capistrano/v2.rb +29 -0
- data/lib/backup_foundation/capistrano/v3.rb +29 -0
- data/lib/backup_foundation/db/base.rb +41 -0
- data/lib/backup_foundation/db/databases.rb +14 -0
- data/lib/backup_foundation/db/mysql.rb +41 -0
- data/lib/backup_foundation/db/postgresql.rb +44 -0
- data/lib/backup_foundation/db/sqlite.rb +29 -0
- data/lib/backup_foundation/job.rb +90 -0
- data/lib/backup_foundation/railtie.rb +7 -0
- data/lib/backup_foundation/tasks/backup_foundation.rake +25 -0
- data/lib/backup_foundation/version.rb +3 -0
- data/lib/generators/backup_foundation/install_generator.rb +13 -0
- data/lib/generators/backup_foundation/templates/initializer.rb +7 -0
- metadata +233 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 574076e67b0d68ad4ab29c88fd7ecf6565a6357d
|
4
|
+
data.tar.gz: def5f5093e23de31cd3362dc8ae1d86dcd4cb5f8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a5a531bab11158295ae60302cc492433d9bc3201f3a329afd22a2ba61b97fd12dc3597fdd5e47fc7aca8993757972269bebe1853c5cc0e7b720e8b3c7bf3ff55
|
7
|
+
data.tar.gz: e65a60cf85a18533aa24502feb6a483ad163b16d09944c78873da106df560866d9793a479a3f1b0f2bb0d6e1f4c9201e6e0371374abb725d6f7978f2f8dd37b8
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Andrew Shaydurov
|
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,69 @@
|
|
1
|
+
# BackupFoundation
|
2
|
+
|
3
|
+
This is a experimental pre-alpha version of backup client ruby gem for [Website cloud backup service Backup.Foundation](https://backup.foundation/). It is not recommended to use it now.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's `Gemfile`:
|
8
|
+
|
9
|
+
gem 'backup_foundation'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
$ bundle exec rails g backup_foundation:install
|
15
|
+
|
16
|
+
Don't forget to set your App Key from [Backup.Foundation](https://backup.foundation/) in `config/initializers/backup_foundation.rb`
|
17
|
+
|
18
|
+
## Usage
|
19
|
+
|
20
|
+
To make a backup and send it to cloud:
|
21
|
+
|
22
|
+
$ bundle exec rake backup_foundation:backup
|
23
|
+
|
24
|
+
To download backup from server and restore it on server:
|
25
|
+
|
26
|
+
$ bundle exec rake backup_foundation:restore
|
27
|
+
|
28
|
+
## Whenever scheduling
|
29
|
+
|
30
|
+
You can schedule making backups with following addition into your `config/schedule.rb`:
|
31
|
+
|
32
|
+
every 1.day, at: '9:30pm' do
|
33
|
+
rake 'backup_foundation:backup'
|
34
|
+
end
|
35
|
+
|
36
|
+
## Capistrano integration
|
37
|
+
|
38
|
+
You can install support for Capistrano by adding following line
|
39
|
+
|
40
|
+
require 'backup_foundation/capistrano'
|
41
|
+
|
42
|
+
into your `Capfile` (for Capistrano 3) or into your `config/deploy.rb` (for Capistrano 2).
|
43
|
+
|
44
|
+
Gem supports two following commands through capistrano:
|
45
|
+
|
46
|
+
$ bundle exec cap production backup_foundation:backup
|
47
|
+
|
48
|
+
And
|
49
|
+
|
50
|
+
$ bundle exec cap production backup_foundation:restore
|
51
|
+
|
52
|
+
By default, commands will be executed on servers in role `app`. You can change it by setting
|
53
|
+
|
54
|
+
set :backup_foundation_roles, ->{ :another_role }
|
55
|
+
|
56
|
+
in Capistrano 3 and
|
57
|
+
|
58
|
+
_cset(:backup_foundation_roles) { :another_role }
|
59
|
+
|
60
|
+
in Capistrano 2 in your `config/deploy.rb`.
|
61
|
+
|
62
|
+
|
63
|
+
## Contributing
|
64
|
+
|
65
|
+
1. Fork it ( https://github.com/sandrew/backup_foundation/fork )
|
66
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
67
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
68
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
69
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'backup_foundation/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "backup_foundation"
|
8
|
+
spec.version = BackupFoundation::VERSION
|
9
|
+
spec.authors = ["Andrew Shaydurov"]
|
10
|
+
spec.email = ["gearhead@it-primorye.ru"]
|
11
|
+
spec.summary = "A client for cloud backuping service Backup.Foundation"
|
12
|
+
spec.description = "This gem contains needed to setup backups for your website in 5 minutes"
|
13
|
+
spec.homepage = "https://backup.foundation"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_runtime_dependency 'rake'
|
22
|
+
spec.add_runtime_dependency 'multi_json'
|
23
|
+
spec.add_runtime_dependency 'multipart-post'
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
26
|
+
spec.add_development_dependency "rspec", "~> 2.5.0"
|
27
|
+
spec.add_development_dependency "rspec-rails", "~> 2.5.0"
|
28
|
+
spec.add_development_dependency "mongo_mapper", ">= 0"
|
29
|
+
spec.add_development_dependency "mongoid", "~> 2.4.4"
|
30
|
+
spec.add_development_dependency "sqlite3", ">= 0"
|
31
|
+
spec.add_development_dependency 'mysql2'
|
32
|
+
spec.add_development_dependency 'pg'
|
33
|
+
spec.add_development_dependency 'whenever'
|
34
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'backup_foundation/version'
|
2
|
+
require 'backup_foundation/db/databases'
|
3
|
+
require 'backup_foundation/job'
|
4
|
+
if defined?(Rails)
|
5
|
+
require 'backup_foundation/railtie'
|
6
|
+
end
|
7
|
+
|
8
|
+
module BackupFoundation
|
9
|
+
HOST = 'https://backup.foundation' # 'http://localhost:3000'
|
10
|
+
|
11
|
+
class << self
|
12
|
+
attr_reader :app_key, :databases, :encryption_key
|
13
|
+
|
14
|
+
def store_app(app_key, &block)
|
15
|
+
@app_key = app_key
|
16
|
+
@databases = []
|
17
|
+
instance_eval &block
|
18
|
+
end
|
19
|
+
|
20
|
+
def encrypt(key)
|
21
|
+
@encryption_key = key
|
22
|
+
end
|
23
|
+
|
24
|
+
def backup_db
|
25
|
+
DB::DATABASES.each do |key, val|
|
26
|
+
if val.respond_to?(:exist?) && val.exist?(Rails.env.to_s)
|
27
|
+
@databases.push({ type: key }.merge(val.get_config(Rails.env.to_s)))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
Capistrano::Configuration.instance(:must_exist).load do
|
2
|
+
_cset(:backup_foundation_roles) { :app }
|
3
|
+
|
4
|
+
load do
|
5
|
+
def backup_foundation_servers
|
6
|
+
find_servers roles: fetch(:backup_foundation_roles)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
namespace :backup_foundation do
|
11
|
+
desc 'Prepare and upload files for backup'
|
12
|
+
task :backup do
|
13
|
+
backup_foundation_servers.each do |server|
|
14
|
+
rake = fetch :rake, 'rake'
|
15
|
+
rails_env = fetch :rails_env, 'production'
|
16
|
+
run "cd '#{current_path}' && #{rake} backup_foundation:backup RAILS_ENV=#{rails_env}", host: server
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'Download and restore files from server'
|
21
|
+
task :restore do
|
22
|
+
backup_foundation_servers.each do |server|
|
23
|
+
rake = fetch :rake, 'rake'
|
24
|
+
rails_env = fetch :rails_env, 'production'
|
25
|
+
run "cd '#{current_path}' && #{rake} backup_foundation:restore RAILS_ENV=#{rails_env}", host: server
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
namespace :backup_foundation do
|
2
|
+
desc 'Prepare and upload files for backup'
|
3
|
+
task :backup do
|
4
|
+
on roles fetch(:backup_foundation_roles) do |host|
|
5
|
+
within release_path do
|
6
|
+
with rails_env: fetch(:rails_env, 'production') do
|
7
|
+
execute :bundle, :exec, :rake, :'backup_foundation:backup'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
desc 'Download and restore files from server'
|
14
|
+
task :restore do
|
15
|
+
on roles fetch(:backup_foundation_roles) do |host|
|
16
|
+
within release_path do
|
17
|
+
with rails_env: fetch(:rails_env, 'production') do
|
18
|
+
execute :bundle, :exec, :rake, :'backup_foundation:restore'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
namespace :load do
|
26
|
+
task :defaults do
|
27
|
+
set :backup_foundation_roles, ->{ :app }
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module BackupFoundation
|
2
|
+
module DB
|
3
|
+
class Base
|
4
|
+
def initialize(options, tmpdir, encryption_key=nil)
|
5
|
+
@options = options
|
6
|
+
@encryption_key = encryption_key
|
7
|
+
@tmpdir = tmpdir
|
8
|
+
end
|
9
|
+
|
10
|
+
def outfile_path
|
11
|
+
"#{@tmpdir}/#{File.basename(@options[:database])}.gz#{'.gpg' if @encryption_key}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def output_to_file(command)
|
15
|
+
"#{command} > #{outfile_path}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def dump_and_encrypt_if_needed(command)
|
19
|
+
if @encryption_key
|
20
|
+
IO.pipe do |rp, wp|
|
21
|
+
wp.puts @encryption_key
|
22
|
+
system output_to_file("#{command} | gzip -cf | gpg --yes --batch --passphrase-fd=3 -q -r -e -c"), 3 => rp
|
23
|
+
end
|
24
|
+
else
|
25
|
+
`#{output_to_file("#{command} | gzip -cf")}`
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def decrypt_if_needed_and_restore(command, infile_path)
|
30
|
+
if @encryption_key
|
31
|
+
IO.pipe do |rp, wp|
|
32
|
+
wp.puts @encryption_key
|
33
|
+
system "cat #{infile_path} | gpg --yes --batch --passphrase-fd=3 -q -r -d | gunzip -c | #{command}", 3 => rp
|
34
|
+
end
|
35
|
+
else
|
36
|
+
`gunzip -c #{infile_path} | #{command}`
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module BackupFoundation
|
2
|
+
module DB
|
3
|
+
autoload :Base, 'backup_foundation/db/base'
|
4
|
+
autoload :MySQL, 'backup_foundation/db/mysql'
|
5
|
+
autoload :PostgreSQL, 'backup_foundation/db/postgresql'
|
6
|
+
autoload :SQLite, 'backup_foundation/db/sqlite'
|
7
|
+
|
8
|
+
DATABASES = {
|
9
|
+
mysql: BackupFoundation::DB::MySQL,
|
10
|
+
postgresql: BackupFoundation::DB::PostgreSQL,
|
11
|
+
sqlite: BackupFoundation::DB::SQLite
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module BackupFoundation
|
2
|
+
module DB
|
3
|
+
class MySQL < Base
|
4
|
+
class << self
|
5
|
+
def exist?(rails_env=nil)
|
6
|
+
defined?(ActiveRecord::Base) &&
|
7
|
+
ActiveRecord::Base.configurations &&
|
8
|
+
ActiveRecord::Base.configurations[rails_env] &&
|
9
|
+
%w(mysql mysql2 mysql2spatial).include?(ActiveRecord::Base.configurations[rails_env]['adapter'])
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_config(rails_env=nil)
|
13
|
+
config = ActiveRecord::Base.configurations[rails_env]
|
14
|
+
{
|
15
|
+
host: config['host'],
|
16
|
+
port: config['port'],
|
17
|
+
user: config['username'],
|
18
|
+
password: config['password'],
|
19
|
+
database: config['database'],
|
20
|
+
socket: config['socket']
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def save_dump(tmpdir)
|
26
|
+
dump_and_encrypt_if_needed "mysqldump #{command_params} --single-transaction #{@options[:database]}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def command_params
|
30
|
+
[:host, :port, :socket, :user, :password].map do |option|
|
31
|
+
next if @options[option].blank?
|
32
|
+
"--#{option}='#{@options[option]}'"
|
33
|
+
end.compact.join ' '
|
34
|
+
end
|
35
|
+
|
36
|
+
def load_dump(infile_path)
|
37
|
+
decrypt_if_needed_and_restore "mysql #{command_params} #{@options[:database]}", infile_path
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module BackupFoundation
|
2
|
+
module DB
|
3
|
+
class PostgreSQL < Base
|
4
|
+
class << self
|
5
|
+
def exist?(rails_env=nil)
|
6
|
+
defined?(ActiveRecord::Base) &&
|
7
|
+
ActiveRecord::Base.configurations &&
|
8
|
+
ActiveRecord::Base.configurations[rails_env] &&
|
9
|
+
ActiveRecord::Base.configurations[rails_env]['adapter'] == 'postgresql'
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_config(rails_env=nil)
|
13
|
+
config = ActiveRecord::Base.configurations[rails_env]
|
14
|
+
{
|
15
|
+
host: config['host'] || config['socket'],
|
16
|
+
port: config['port'],
|
17
|
+
username: config['username'],
|
18
|
+
password: config['password'],
|
19
|
+
database: config['database']
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def save_dump(tmpdir)
|
25
|
+
dump_and_encrypt_if_needed "#{command_password_variable} pg_dump #{command_params} #{@options[:database]}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def command_params
|
29
|
+
[:host, :port, :username].map do |option|
|
30
|
+
next if @options[option].blank?
|
31
|
+
"--#{option}='#{@options[option]}'"
|
32
|
+
end.compact.join ' '
|
33
|
+
end
|
34
|
+
|
35
|
+
def command_password_variable
|
36
|
+
@options[:password].blank? ? '' : "PGPASSWORD='#{@options[:password]}'"
|
37
|
+
end
|
38
|
+
|
39
|
+
def load_dump(infile_path)
|
40
|
+
decrypt_if_needed_and_restore "#{command_password_variable} psql #{command_params} #{@options[:database]}", infile_path
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module BackupFoundation
|
2
|
+
module DB
|
3
|
+
class SQLite < Base
|
4
|
+
class << self
|
5
|
+
def exist?(rails_env=nil)
|
6
|
+
defined?(ActiveRecord::Base) &&
|
7
|
+
ActiveRecord::Base.configurations &&
|
8
|
+
ActiveRecord::Base.configurations[rails_env] &&
|
9
|
+
ActiveRecord::Base.configurations[rails_env]['adapter'] == 'sqlite3'
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_config(rails_env=nil)
|
13
|
+
config = ActiveRecord::Base.configurations[rails_env]
|
14
|
+
{
|
15
|
+
database: config['database']
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def save_dump(tmpdir)
|
21
|
+
dump_and_encrypt_if_needed "cat #{@options[:database]}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def load_dump(infile_path)
|
25
|
+
decrypt_if_needed_and_restore "cat > #{@options[:database]}", infile_path
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'net/http/post/multipart'
|
2
|
+
require 'backup_foundation/db/databases'
|
3
|
+
|
4
|
+
module BackupFoundation
|
5
|
+
class Job
|
6
|
+
def initialize(params)
|
7
|
+
@params = params
|
8
|
+
end
|
9
|
+
|
10
|
+
def backup!
|
11
|
+
for_each_db do |db, tmpdir|
|
12
|
+
(dumper = BackupFoundation::DB::DATABASES[db[:type].to_sym].new(db, tmpdir, @params['encryption_key'])).save_dump tmpdir
|
13
|
+
if File.exist? dumper.outfile_path
|
14
|
+
send_db_dump dumper.outfile_path, db
|
15
|
+
FileUtils.remove_entry_secure dumper.outfile_path
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def restore!
|
21
|
+
for_each_db do |db, tmpdir|
|
22
|
+
file_path = download_db_dump tmpdir, db
|
23
|
+
if File.exist? file_path
|
24
|
+
BackupFoundation::DB::DATABASES[db[:type].to_sym].new(db, tmpdir, @params['encryption_key']).load_dump file_path
|
25
|
+
FileUtils.remove_entry_secure file_path
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def for_each_db(&block)
|
31
|
+
tmpdir = Dir.mktmpdir
|
32
|
+
@params['dbs'].each do |db|
|
33
|
+
unless defined?(HashWithIndifferentAccess) && db.is_a?(HashWithIndifferentAccess)
|
34
|
+
db.each { |key, val| db[key.to_sym] = db.delete(key) }
|
35
|
+
end
|
36
|
+
yield db, tmpdir
|
37
|
+
end
|
38
|
+
FileUtils.remove_entry_secure(tmpdir) if tmpdir and File.exist?(tmpdir)
|
39
|
+
end
|
40
|
+
|
41
|
+
def send_db_dump(file, db)
|
42
|
+
url = URI.parse "#{BackupFoundation::HOST}/api/file"
|
43
|
+
upload_file = UploadIO.new(file, 'application/octet-stream', db[:type].to_s)
|
44
|
+
request = Net::HTTP::Post::Multipart.new url.path,
|
45
|
+
'file' => upload_file,
|
46
|
+
'key' => @params['key'],
|
47
|
+
'gz' => 'on',
|
48
|
+
'gpg' => @params['encryption_key'] ? 'on' : 'off',
|
49
|
+
'md5' => Digest::MD5.hexdigest(File.read(file))
|
50
|
+
|
51
|
+
http = Net::HTTP.new url.host, url.port
|
52
|
+
if url.is_a? URI::HTTPS
|
53
|
+
http.use_ssl = true
|
54
|
+
# for debug
|
55
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
56
|
+
end
|
57
|
+
|
58
|
+
retry_count = 0
|
59
|
+
begin
|
60
|
+
http.request request
|
61
|
+
rescue Exception => e
|
62
|
+
if retry_count < 8
|
63
|
+
retry_count += 1
|
64
|
+
upload_file.rewind
|
65
|
+
sleep 2 ** retry_count
|
66
|
+
retry
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def download_db_dump(tmpdir, db)
|
72
|
+
file_path = nil
|
73
|
+
url = URI.parse "#{BackupFoundation::HOST}/api/file?key=#{@params['key']}&name=#{db[:type]}"
|
74
|
+
http = Net::HTTP.new url.host, url.port
|
75
|
+
if url.is_a? URI::HTTPS
|
76
|
+
http.use_ssl = true
|
77
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
78
|
+
end
|
79
|
+
http.request_get(url.request_uri) do |response|
|
80
|
+
file_path = "#{tmpdir}/#{response['Content-Disposition'][/"(.*)"/, 1]}"
|
81
|
+
File.open file_path, 'wb' do |file|
|
82
|
+
response.read_body do |str|
|
83
|
+
file.write str
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
file_path
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
namespace :backup_foundation do
|
2
|
+
desc 'Prepare and upload files for backup'
|
3
|
+
task backup: :environment do
|
4
|
+
opts = HashWithIndifferentAccess.new \
|
5
|
+
key: BackupFoundation.app_key,
|
6
|
+
dbs: BackupFoundation.databases,
|
7
|
+
encryption_key: BackupFoundation.encryption_key
|
8
|
+
job = BackupFoundation::Job.new(opts).backup!
|
9
|
+
end
|
10
|
+
|
11
|
+
# desc 'Support task. Makes all dirty job'
|
12
|
+
# task :dump_and_send, :params do |t, params|
|
13
|
+
# require File.expand_path("../../job", __FILE__)
|
14
|
+
# BackupFoundation::Job.new(MultiJson.load(params[:params])).backup!
|
15
|
+
# end
|
16
|
+
|
17
|
+
desc 'Download and restore files from server'
|
18
|
+
task restore: :environment do
|
19
|
+
opts = HashWithIndifferentAccess.new \
|
20
|
+
key: BackupFoundation.app_key,
|
21
|
+
dbs: BackupFoundation.databases,
|
22
|
+
encryption_key: BackupFoundation.encryption_key
|
23
|
+
job = BackupFoundation::Job.new(opts).restore!
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module BackupFoundation
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path("../templates", __FILE__)
|
5
|
+
|
6
|
+
desc 'This generator creates an initializer file at config/initializers'
|
7
|
+
|
8
|
+
def copy_initializer_file
|
9
|
+
template 'initializer.rb', 'config/initializers/backup_foundation.rb'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
metadata
ADDED
@@ -0,0 +1,233 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: backup_foundation
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrew Shaydurov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-07-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
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: multi_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: multipart-post
|
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: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.6'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.6'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 2.5.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 2.5.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec-rails
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 2.5.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 2.5.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: mongo_mapper
|
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
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: mongoid
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 2.4.4
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 2.4.4
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: sqlite3
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: mysql2
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: pg
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: whenever
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
description: This gem contains needed to setup backups for your website in 5 minutes
|
182
|
+
email:
|
183
|
+
- gearhead@it-primorye.ru
|
184
|
+
executables: []
|
185
|
+
extensions: []
|
186
|
+
extra_rdoc_files: []
|
187
|
+
files:
|
188
|
+
- ".gitignore"
|
189
|
+
- Gemfile
|
190
|
+
- LICENSE.txt
|
191
|
+
- README.md
|
192
|
+
- Rakefile
|
193
|
+
- backup_foundation.gemspec
|
194
|
+
- lib/backup_foundation.rb
|
195
|
+
- lib/backup_foundation/capistrano.rb
|
196
|
+
- lib/backup_foundation/capistrano/v2.rb
|
197
|
+
- lib/backup_foundation/capistrano/v3.rb
|
198
|
+
- lib/backup_foundation/db/base.rb
|
199
|
+
- lib/backup_foundation/db/databases.rb
|
200
|
+
- lib/backup_foundation/db/mysql.rb
|
201
|
+
- lib/backup_foundation/db/postgresql.rb
|
202
|
+
- lib/backup_foundation/db/sqlite.rb
|
203
|
+
- lib/backup_foundation/job.rb
|
204
|
+
- lib/backup_foundation/railtie.rb
|
205
|
+
- lib/backup_foundation/tasks/backup_foundation.rake
|
206
|
+
- lib/backup_foundation/version.rb
|
207
|
+
- lib/generators/backup_foundation/install_generator.rb
|
208
|
+
- lib/generators/backup_foundation/templates/initializer.rb
|
209
|
+
homepage: https://backup.foundation
|
210
|
+
licenses:
|
211
|
+
- MIT
|
212
|
+
metadata: {}
|
213
|
+
post_install_message:
|
214
|
+
rdoc_options: []
|
215
|
+
require_paths:
|
216
|
+
- lib
|
217
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
218
|
+
requirements:
|
219
|
+
- - ">="
|
220
|
+
- !ruby/object:Gem::Version
|
221
|
+
version: '0'
|
222
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
223
|
+
requirements:
|
224
|
+
- - ">="
|
225
|
+
- !ruby/object:Gem::Version
|
226
|
+
version: '0'
|
227
|
+
requirements: []
|
228
|
+
rubyforge_project:
|
229
|
+
rubygems_version: 2.2.2
|
230
|
+
signing_key:
|
231
|
+
specification_version: 4
|
232
|
+
summary: A client for cloud backuping service Backup.Foundation
|
233
|
+
test_files: []
|