backup-rails 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ Y2ZiNjBmNjIyY2Q2OTJmNzYyMWIxYzhmYzA0M2UxYTMwYTFkZWYyZA==
5
+ data.tar.gz: !binary |-
6
+ OGE5ODc1NTk0Yjg5MTBkNTRkM2Q4M2NjYTUyYzIyZjU2NjgwYTY5Ng==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ YTQwODczYjIxNGZmYTQ5OWQ3ZGEzMGQ5MDBlZTc1NzY0MDA2ZGM1NWMyYzA2
10
+ MWJkOTE1OWM2MTBmYzFiMTEwZTE2NWUzODYzZTk4YzIyNWZkYjJiNDVmOWQw
11
+ OTdjNDhhMmQwODE2OWEyMDI5MWRiMTljYzM0ZTE3YjU1ZWJmNWE=
12
+ data.tar.gz: !binary |-
13
+ N2Q0Y2Q4NTkxZmJmODA4NzczZTk1OWMyMTBhMzFiNjkzMWJmYzY4MGRmOGYy
14
+ NDAwYWZiZWM4ZmI0ODM4MzM5ZWRhZjFkYmI0N2NkYmY1ZmFmZjI2OWIzNTVh
15
+ YjMyYmQ5MWIxMGY4ODgwOTYwZjNhZjRhNDQ0MDM5Y2I5N2VjNmM=
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .env
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --fail-fast
3
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,23 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :development, :test do
4
+ gem 'guard'
5
+ gem 'guard-rspec'
6
+ gem 'guard-bundler'
7
+
8
+ gem 'rspec'
9
+ #gem 'generator_spec', github: "jesson/generator_spec"
10
+ gem 'rb-inotify'
11
+ gem 'thor'
12
+
13
+ gem 'rails', '~> 3.2.16'
14
+ gem 'sqlite3'
15
+ gem 'mysql2'
16
+ gem 'mongoid'
17
+ gem 'pg'
18
+ gem 'bson_ext'
19
+ end
20
+
21
+ # Specify your gem's dependencies in backup-rails.gemspec
22
+ gemspec
23
+
data/Guardfile ADDED
@@ -0,0 +1,31 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'bundler' do
5
+ watch('Gemfile')
6
+ # Uncomment next line if Gemfile contain `gemspec' command
7
+ # watch(/^.+\.gemspec/)
8
+ end
9
+
10
+ guard 'rspec', cli: "--fail-fast" do
11
+ watch(%r{^spec/.+_spec\.rb$})
12
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
13
+ watch('spec/spec_helper.rb') { "spec" }
14
+
15
+ # Rails example
16
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
17
+ watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
18
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
19
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
20
+ watch('config/routes.rb') { "spec/routing" }
21
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
22
+
23
+ # Capybara features specs
24
+ watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
25
+
26
+ # Turnip features and steps
27
+ watch(%r{^spec/acceptance/(.+)\.feature$})
28
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
29
+ end
30
+
31
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Oleg Bavaev
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,29 @@
1
+ # Backup::Rails
2
+
3
+ Backup rails project with backup & whenever gems
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'backup-rails'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install backup-rails
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'backup-rails/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "backup-rails"
8
+ gem.version = Backup::Rails::VERSION
9
+ gem.authors = ["Oleg Bavaev"]
10
+ gem.email = ["jesoba7@gmail.com"]
11
+ gem.description = %q{Backup rails project with backup & whenever gems}
12
+ gem.summary = %q{Backup rails project}
13
+ gem.homepage = "https://github.com/jesson/backup-rails"
14
+ gem.license = "MIT"
15
+
16
+ gem.files = `git ls-files`.split($/)
17
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.require_paths = ["lib"]
20
+
21
+ gem.add_dependency 'backup', '>= 3.4.0'
22
+ gem.add_dependency 'whenever'
23
+ gem.add_dependency 'dotenv-rails'
24
+ gem.add_dependency 'fog', '~> 1.9'
25
+ gem.add_dependency 'net-ssh', '>= 2.3.0', '<= 2.5.2'
26
+ gem.add_dependency 'excon', '~> 0.17.0'
27
+ end
28
+
data/bin/backup_rails ADDED
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env ruby
2
+ require 'thor'
3
+ require 'dotenv'
4
+ require 'yaml'
5
+
6
+ class BackupRailsCLI < Thor
7
+ include Thor::Actions
8
+
9
+ def self.source_root
10
+ File.dirname(__FILE__)
11
+ end
12
+
13
+ desc "restore ARCHIVE DESTINATION", "Restore files from backup file"
14
+ method_option :ssl_password,
15
+ :aliases => ['-sp'],
16
+ :required => false,
17
+ :type => :string,
18
+ :desc => "password for SSL encrypt"
19
+ def restore archive_path, destination_path
20
+ puts "Restoring from #{archive_path}"
21
+
22
+ Dotenv.load
23
+
24
+ dir = Dir.mktmpdir
25
+
26
+ begin
27
+ if options[:ssl_password]
28
+ # decrypt & untar
29
+ create_file dir + "/simple.txt", options[:ssl_password]
30
+ system "cd #{dir} && openssl aes-256-cbc -d -base64 -pass file:simple.txt -in #{archive_path} -out restore.tar && rm simple.txt"
31
+ system "cd #{dir} && tar -xf restore.tar"
32
+ else
33
+ # untar
34
+ system "cd #{dir} && tar -xf #{archive_path}"
35
+ end
36
+ # unpacking code
37
+ system "mkdir -p #{destination_path} && cd #{destination_path} && tar -xf #{dir}/general/archives/code.tar.gz"
38
+
39
+ # restore database
40
+ environment = 'production'
41
+ if File.exists? destination_path + "/config/database.yml"
42
+ dbconfig = YAML::load(ERB.new(IO.read(File.join(destination_path, 'config', 'database.yml'))).result)[environment]
43
+
44
+ if dbconfig['adapter'] == 'mysql2'
45
+ run "echo \"create database #{dbconfig['database']}\" | mysql -u #{dbconfig['username']} --password=#{dbconfig['password']}"
46
+ run "cd #{dir}/general/databases && gzip -d MySQL.sql.gz"
47
+ run "cd #{dir}/general/databases && mysql -u #{dbconfig['username']} --password=#{dbconfig['password']} #{dbconfig['database']} < MySQL.sql"
48
+ elsif dbconfig['adapter'] == 'postgresql'
49
+ run "export PGPASSWORD=#{dbconfig['password']} && createdb -U#{dbconfig['username']} #{dbconfig['database']}"
50
+ run "cd #{dir}/general/databases && gzip -d PostgreSQL.sql.gz"
51
+ run "cd #{dir}/general/databases && export PGPASSWORD=#{dbconfig['password']} && psql -U#{dbconfig['username']} #{dbconfig['database']} < PostgreSQL.sql"
52
+ end
53
+ end
54
+ # mongoid
55
+ if File.exists? destination_path + "/config/mongoid.yml"
56
+ dbconfig = YAML::load(ERB.new(IO.read(File.join(destination_path, 'config', 'mongoid.yml'))).result)[environment]
57
+ dbconfig = dbconfig['sessions']['default']
58
+ run "cd #{dir}/general/databases && tar -xf MongoDB.tar.gz"
59
+ options = { username: dbconfig['username'], password: dbconfig['password'], db: dbconfig['database'] }
60
+ params = options.select {|k,v| !v.nil? && !v.empty? }.map {|k,v| "--#{k} #{v}"}.join(" ")
61
+ run "cd #{dir}/general/databases && mongorestore #{params} #{dir}/general/databases/MongoDB/#{dbconfig['database']}"
62
+ end
63
+
64
+ ensure
65
+ # remove the directory.
66
+ #FileUtils.remove_entry_secure dir
67
+ end
68
+ end
69
+ end
70
+
71
+ BackupRailsCLI.start
@@ -0,0 +1,5 @@
1
+ module Backup
2
+ module Rails
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -0,0 +1,12 @@
1
+ require "backup-rails/version"
2
+ require "rails"
3
+
4
+ module Backup
5
+ module Rails
6
+ class Railtie < ::Rails::Railtie
7
+ rake_tasks do
8
+ load "tasks/backup.rake"
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,32 @@
1
+ require 'rails/generators'
2
+
3
+ module Backup
4
+ module Rails
5
+ module Generators
6
+ class InstallGenerator < ::Rails::Generators::Base
7
+ desc "Generates configurations for backup and whenever"
8
+
9
+ def self.source_root
10
+ @source_root ||= File.join(File.dirname(__FILE__), 'templates')
11
+ end
12
+
13
+ # Generator Code. Remember this is just suped-up Thor so methods are executed in order
14
+ def install
15
+ run "bundle exec backup generate:config --config-path=config/backup" unless File.exists?("config/backup/config.rb")
16
+ template "general.rb", "config/backup/models/general.rb"
17
+ if File.exists? ".env"
18
+ append_file ".env" do
19
+ File.read(File.expand_path(find_in_source_paths('.env')))
20
+ end
21
+ else
22
+ template ".env"
23
+ end
24
+ run "bundle exec wheneverize ." unless File.exists?("config/schedule.rb")
25
+ append_file "config/schedule.rb" do
26
+ File.read(File.expand_path(find_in_source_paths('schedule.rb')))
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,113 @@
1
+ # encoding: utf-8
2
+ require 'dotenv'
3
+ require "rails"
4
+
5
+ ##
6
+ # Backup Generated: general
7
+ # Once configured, you can run the backup with the following command:
8
+ #
9
+ # $ backup perform -t general [-c <path_to_configuration_file>]
10
+ #
11
+ Backup::Model.new(:general, 'Description for general') do
12
+ Dotenv.load
13
+
14
+ root_path = File.dirname(__FILE__)
15
+ archive :code do |archive|
16
+ archive.root root_path
17
+ archive.add "."
18
+ archive.exclude root_path + '/log'
19
+ archive.exclude root_path + '/tmp'
20
+ end
21
+
22
+ compress_with Gzip do
23
+
24
+ end
25
+
26
+ if ENV['SSL_PASSWORD']
27
+ encrypt_with OpenSSL do |encryption|
28
+ encryption.password = ENV['SSL_PASSWORD']
29
+ encryption.base64 = true
30
+ encryption.salt = true
31
+ end
32
+ end
33
+
34
+ if File.exists? root_path + "/config/database.yml"
35
+ environment = 'production'
36
+ dbconfig = YAML::load(ERB.new(IO.read(File.join(root_path, 'config', 'database.yml'))).result)[environment]
37
+ if dbconfig['adapter'] == 'mysql2'
38
+ database MySQL do |db|
39
+ db.name = dbconfig['database']
40
+ db.username = dbconfig['username']
41
+ db.password = dbconfig['password']
42
+ db.host = dbconfig['host']
43
+ db.port = dbconfig['port']
44
+ db.socket = dbconfig['socket']
45
+ end
46
+ elsif dbconfig['adapter'] == 'postgresql'
47
+ database PostgreSQL do |db|
48
+ db.name = dbconfig['database']
49
+ db.username = dbconfig['username']
50
+ db.password = dbconfig['password']
51
+ db.host = dbconfig['host']
52
+ db.port = dbconfig['port']
53
+ db.socket = dbconfig['socket']
54
+ end
55
+ end
56
+ end
57
+
58
+ if File.exists? root_path + "/config/mongoid.yml"
59
+ environment = 'production'
60
+ dbconfig = YAML::load(ERB.new(IO.read(File.join(root_path, 'config', 'mongoid.yml'))).result)[environment]
61
+ if dbconfig
62
+ database MongoDB do |db|
63
+ db.name = dbconfig['sessions']['default']['database']
64
+ db.username = dbconfig['sessions']['default']['username']
65
+ db.password = dbconfig['sessions']['default']['password']
66
+ #db.host = dbconfig['host']
67
+ #db.port = dbconfig['port']
68
+ db.ipv6 = false
69
+ db.lock = false
70
+ db.oplog = false
71
+ end
72
+ end
73
+ end
74
+
75
+ if ENV['LOCAL_PATH']
76
+ store_with Local do |local|
77
+ local.path = ENV['LOCAL_PATH']
78
+ local.keep = 5
79
+ end
80
+ end
81
+
82
+ if ENV['S3_ACCESS_KEY_ID'] && ENV['S3_SECRET_ACCESS_KEY'] && ENV['S3_BUCKET']
83
+ store_with S3 do |s3|
84
+ # AWS Credentials
85
+ s3.access_key_id = ENV['S3_ACCESS_KEY_ID']
86
+ s3.secret_access_key = ENV['S3_SECRET_ACCESS_KEY']
87
+ # Or, to use a IAM Profile:
88
+ # s3.use_iam_profile = true
89
+
90
+ s3.region = ENV['S3_REGION']
91
+ s3.bucket = ENV['S3_BUCKET']
92
+ #s3.path = ENV['S3_PATH']
93
+ end
94
+ end
95
+
96
+ if ENV['NOTIFY_MAIL_USER_NAME']
97
+ notify_by Mail do |mail|
98
+ mail.on_success = true
99
+ mail.on_warning = true
100
+ mail.on_failure = true
101
+
102
+ mail.from = ENV['NOTIFY_MAIL_FROM']
103
+ mail.to = ENV['NOTIFY_MAIL_TO']
104
+ mail.address = ENV['NOTIFY_MAIL_ADDRESS']
105
+ mail.port = ENV['NOTIFY_MAIL_PORT']
106
+ mail.domain = ENV['NOTIFY_MAIL_DOMAIN']
107
+ mail.user_name = ENV['NOTIFY_MAIL_USER_NAME']
108
+ mail.password = ENV['NOTIFY_MAIL_PASSWORD']
109
+ mail.authentication = ENV['NOTIFY_MAIL_AUTHENTICATION']
110
+ mail.encryption = :starttls
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,4 @@
1
+
2
+ every :day, :at => '3:30am' do
3
+ rake 'backup:backup'
4
+ end
@@ -0,0 +1,9 @@
1
+ namespace "backup" do
2
+ task "backup" => :environment do
3
+ system "bundle exec backup perform -t general -c config/backup/config.rb -l tmp/backup/log -d tmp/backup/data --tmp-path=tmp/backup/tmp --cache-path=tmp/backup/cache"
4
+ end
5
+
6
+ task "restore" => :environment do
7
+ Backup::Config.load Rails.root.join + 'config/backup/config.rb'
8
+ end
9
+ end
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env ruby
2
+ require 'thor'
3
+
4
+ class PrepareForTesting < Thor
5
+ include Thor::Actions
6
+
7
+ def self.source_root
8
+ File.dirname(__FILE__)
9
+ end
10
+
11
+ desc "Generate", "Generate rails apps for testing"
12
+ def generate
13
+ destination_root = File.dirname(__FILE__) + "/../../tmp"
14
+ dbname = "backup_rails"
15
+ username = "backup_rails"
16
+ password = "123123123"
17
+ inside destination_root do
18
+ rails_versions = %w(3.2.16)
19
+ rails_versions.each do |rails_version|
20
+ %w(sqlite3 mysql mongodb postgresql).each do |database_type|
21
+ path = "test_#{rails_version}_#{database_type}"
22
+ remove_dir path
23
+ run "gem install rails -v #{rails_version} --conservative"
24
+ case database_type
25
+ when 'sqlite3'
26
+ run "rails _#{rails_version}_ new #{path} -d sqlite3 -B"
27
+ when 'mysql'
28
+ run "rails _#{rails_version}_ new #{path} -d mysql -B"
29
+ when 'postgresql'
30
+ run "rails _#{rails_version}_ new #{path} -d postgresql -B"
31
+ when 'mongodb'
32
+ run "rails _#{rails_version}_ new #{path} -O -B"
33
+ end
34
+ inside path do
35
+ if %w(mysql postgresql).include? database_type
36
+ gsub_file "config/database.yml", /database:(.+)$/, "database: #{dbname}"
37
+ gsub_file "config/database.yml", /username:(.+)$/, "username: #{username}"
38
+ gsub_file "config/database.yml", /password:(.*)$/, "password: '#{password}'"
39
+ end
40
+ gsub_file "config/environments/development.rb", "config.action_mailer", "# config.action_mailer"
41
+ append_file "Gemfile", "gem 'backup-rails', path: '../../'\n"
42
+
43
+ if database_type == "mongodb"
44
+ if rails_version == "3.2.16"
45
+ append_file "Gemfile", "gem 'mongoid'\n"
46
+ else
47
+ append_file "Gemfile", "gem 'mongoid', github: 'mongoid/mongoid'\n"
48
+ end
49
+ end
50
+
51
+ run "bundle install"
52
+ run "rails generate mongoid:config" if database_type == "mongodb"
53
+ if database_type == 'mongodb'
54
+ gsub_file "config/mongoid.yml", /database: (.+)$/, "database: #{dbname}"
55
+ append_file "config/mongoid.yml",
56
+ <<-eos
57
+ production:
58
+ sessions:
59
+ default:
60
+ hosts:
61
+ - localhost:27017
62
+ database: #{dbname}
63
+ eos
64
+ end
65
+ run "rails generate scaffold post title:string body:text published_at:datetime"
66
+ run "rake db:drop"
67
+ run "rake db:create"
68
+ run "rake db:migrate"
69
+ remove_file "db/seeds.rb"
70
+ create_file "db/seeds.rb", "10.times.each {|i| Post.create!(title: 'Title!', body: 'fjasdfhiwue72h3jh', published_at: Time.now)}"
71
+ run "rake db:seed"
72
+
73
+ # dump
74
+ case database_type
75
+ when 'mysql'
76
+ run "mysqldump -u#{username} --password=#{password} #{dbname} > mysqldump.sql"
77
+ when 'postgresql'
78
+ run "export PGPASSWORD=#{password} && pg_dump --username=#{username} #{dbname} > pgsqldump.sql"
79
+ when 'mongodb'
80
+ run "mongodump --db #{dbname} --out mongodump"
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ end
89
+
90
+ PrepareForTesting.start
@@ -0,0 +1,72 @@
1
+ require "spec_helper"
2
+ require "generators/backup/rails/install_generator"
3
+
4
+ describe Backup::Rails::Generators::InstallGenerator do
5
+ let(:tmp_path) { File.expand_path("../../../../../../tmp", __FILE__) }
6
+
7
+ let(:dbname) { "backup_rails" }
8
+ let(:username) { "backup_rails" }
9
+ let(:password) { "123123123" }
10
+
11
+ let(:ssl_password) { "123123123" }
12
+ let(:backup_path) { tmp_path + "/backups" }
13
+
14
+ # Crypt variants
15
+ [false, true].each do |with_crypt|
16
+
17
+ # Database type variants
18
+ %w(sqlite3 mysql mongodb postgresql).each do |database_type|
19
+
20
+ # Storage type variants
21
+ %w(local S3).each do |storage_type|
22
+ context "Code + #{database_type.capitalize} => #{storage_type.capitalize} => With#{!with_crypt ? "out":""} crypt" do
23
+
24
+ # Rails version variants
25
+ %w(3.2.16).each do |rails_version|
26
+ context "(rails #{rails_version})" do
27
+ let(:test_rails_project_path) { "test_#{rails_version}_#{database_type}" }
28
+
29
+ it "backups & restores" do
30
+ # prepare project
31
+ prepare_project
32
+
33
+ # rails generate backup_rails:install
34
+ install_config
35
+
36
+ # restore database
37
+ restore_database(database_type)
38
+
39
+ assert_file "Gemfile", /gem 'backup-rails'/
40
+ assert_file "config/backup/config.rb"
41
+ assert_file "config/backup/models/general.rb"
42
+ assert_file "config/schedule.rb"
43
+ assert_file ".env"
44
+
45
+ # fill .env
46
+ write_env(storage_type, with_crypt)
47
+
48
+ # backup
49
+ backup_project
50
+
51
+ # drop database
52
+ drop_database(database_type)
53
+
54
+ # check remote storage
55
+ check_remote_storage(storage_type)
56
+
57
+ # restore
58
+ restore_project(with_crypt)
59
+
60
+ # check code
61
+ expect(compare_dirs(tmp_path + '/test_generator', tmp_path + '/test_generator_restore')).to be_true
62
+
63
+ # check database
64
+ expect(check_database(database_type)).to be_true
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,26 @@
1
+ #require 'rails'
2
+ #require 'backup-rails'
3
+
4
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
5
+
6
+ class RSpec::Core::ExampleGroup
7
+ def self.run_all(reporter=nil)
8
+ run(reporter || RSpec::Mocks::Mock.new('reporter').as_null_object)
9
+ end
10
+ end
11
+
12
+ RSpec.configure do |config|
13
+ config.treat_symbols_as_metadata_keys_with_true_values = true
14
+ config.filter_run :focus
15
+ config.run_all_when_everything_filtered = true
16
+ config.before(:each) do
17
+ @real_world = RSpec.world
18
+ RSpec.instance_variable_set(:@world, RSpec::Core::World.new)
19
+ end
20
+ config.after(:each) do
21
+ RSpec.instance_variable_set(:@world, @real_world)
22
+ end
23
+ config.order = :random
24
+
25
+ config.include CustomMatchers
26
+ end
@@ -0,0 +1,168 @@
1
+ require 'mysql2'
2
+ require 'mongoid'
3
+ require 'dotenv'
4
+ require 'fog'
5
+ require 'pg'
6
+
7
+ class Post
8
+ include Mongoid::Document
9
+ field :title
10
+ end
11
+
12
+ module CustomMatchers
13
+ def assert_file(relative, *contents)
14
+ absolute = File.expand_path(relative, tmp_path + "/test_generator")
15
+ expect(File).to be_exists(absolute), "Expected file #{relative.inspect} to exist, but does not"
16
+
17
+ read = File.read(absolute) if block_given? || !contents.empty?
18
+ yield read if block_given?
19
+
20
+ contents.each do |content|
21
+ case content
22
+ when String
23
+ expect(content).to eq read
24
+ when Regexp
25
+ expect(content).to match read
26
+ end
27
+ end
28
+ end
29
+
30
+ def sameFile path1, path2
31
+ return File.stat(path1).size == File.stat(path2).size
32
+ end
33
+
34
+ def compare_dirs dir1, dir2
35
+ return false unless File.exists?(dir1) && File.exists?(dir2)
36
+ Dir.foreach(dir1) do |item|
37
+ next if item == "." or item == ".."
38
+ path1 = File.join(dir1, item)
39
+ path2 = File.join(dir1, item)
40
+ if File.directory?(path1)
41
+ next if File.symlink? path1
42
+ return false unless File.directory? path2
43
+
44
+ compare_dirs(path1, path2)
45
+ else
46
+ return false unless File.file? path2
47
+ return false unless sameFile(path1, path2)
48
+ end
49
+ end
50
+ true
51
+ end
52
+
53
+ def check_database database_type
54
+ case database_type
55
+ when 'mysql'
56
+ client = Mysql2::Client.new(:host => "localhost", :username => username, database: dbname, password: password)
57
+ return client.query("select * from posts").count == 10
58
+ when 'mongodb'
59
+ Mongoid.configure.connect_to("backup_rails")
60
+ return Post.count == 10
61
+ when 'postgresql'
62
+ conn = PG::Connection.new(dbname: dbname, user: username, password: password)
63
+ return conn.exec("select * from posts").values.size == 10
64
+ when 'sqlite3'
65
+ return true
66
+ end
67
+ end
68
+
69
+ def restore_database database_type
70
+ output = ""
71
+ output += drop_database database_type
72
+ case database_type
73
+ when 'mysql'
74
+ output += run "echo \"create database #{dbname}\" | mysql -u #{username} --password=#{password}"
75
+ output += run "cd #{tmp_path}/test_generator && mysql -u #{username} --password=#{password} #{dbname} < mysqldump.sql"
76
+ when 'mongodb'
77
+ output += run "cd #{tmp_path}/test_generator && mongorestore --db backup_rails mongodump/backup_rails"
78
+ when 'postgresql'
79
+ output += run "export PGPASSWORD=#{password} && createdb -U#{username} #{dbname}", false
80
+ output += run "cd #{tmp_path}/test_generator && export PGPASSWORD=#{password} && psql -U#{username} #{dbname} < pgsqldump.sql"
81
+ end
82
+ output
83
+ end
84
+
85
+ def drop_database database_type
86
+ output = ""
87
+ case database_type
88
+ when 'mysql'
89
+ output += run "echo \"drop database #{dbname}\" | mysql -u #{username} --password=#{password}", false
90
+ when 'mongodb'
91
+ output += run "cd #{tmp_path}/test_generator && mongo backup_rails --eval \"db.dropDatabase()\"", false
92
+ when 'postgresql'
93
+ output += run "export PGPASSWORD=#{password} && dropdb -U#{username} #{dbname}", false
94
+ end
95
+ output
96
+ end
97
+
98
+ def write_env storage_type, with_crypt
99
+ Dotenv.load
100
+ File.open(tmp_path + "/test_generator/.env", "w") do |f|
101
+ f.write("SSL_PASSWORD=#{ssl_password}\n") if with_crypt
102
+ case storage_type
103
+ when 'local'
104
+ f.write("LOCAL_PATH=#{backup_path}")
105
+ when 'S3'
106
+ f.write("S3_ACCESS_KEY_ID=\"#{ENV['S3_ACCESS_KEY_ID']}\"\n")
107
+ f.write("S3_SECRET_ACCESS_KEY=\"#{ENV['S3_SECRET_ACCESS_KEY']}\"\n")
108
+ f.write("S3_REGION=\"#{ENV['S3_REGION']}\"\n")
109
+ f.write("S3_BUCKET=\"#{ENV['S3_BUCKET']}\"\n")
110
+ f.write("S3_PATH=\"#{ENV['S3_PATH']}\"\n")
111
+ end
112
+ end
113
+ end
114
+
115
+ def check_remote_storage storage_type
116
+ case storage_type
117
+ when 'S3'
118
+ connection = Fog::Storage.new({
119
+ :provider => 'AWS',
120
+ :aws_access_key_id => ENV['S3_ACCESS_KEY_ID'],
121
+ :aws_secret_access_key => ENV['S3_SECRET_ACCESS_KEY']
122
+ })
123
+ dir = connection.directories.detect { | dir | dir.key == ENV["S3_BUCKET"] }
124
+ file = dir.files.max_by {|f| f.last_modified }
125
+ file_path = File.expand_path(file.key, tmp_path)
126
+ path = File.dirname(file_path)
127
+ run "mkdir -p #{path}"
128
+ File.open(file_path, "wb") do |f|
129
+ f.write file.body
130
+ end
131
+ end
132
+ end
133
+
134
+ def restore_project with_crypt
135
+ run "cd #{tmp_path} && rm -fr test_generator_restore"
136
+ if with_crypt
137
+ archive_path = Dir[backup_path + "/general/*/general.tar.enc"].first
138
+ run "cd #{tmp_path} && ../bin/backup_rails restore #{archive_path} #{tmp_path}/test_generator_restore --ssl_password=#{ssl_password}"
139
+ else
140
+ archive_path = Dir[backup_path + "/general/*/general.tar"].first
141
+ run "cd #{tmp_path} && ../bin/backup_rails restore #{archive_path} #{tmp_path}/test_generator_restore"
142
+ end
143
+ end
144
+
145
+ def prepare_project
146
+ run "cd #{tmp_path} && rm -fr test_generator && cp -r #{test_rails_project_path} test_generator"
147
+ end
148
+
149
+ def install_config
150
+ run "cd #{tmp_path}/test_generator && rails generate backup:rails:install"
151
+ end
152
+
153
+ def run command, check_exitstatus=true
154
+ output = %x(#{command})
155
+ p output unless $?.success?
156
+ $?.success?.should be_true, "Error run command: #{command}" if check_exitstatus
157
+ output
158
+ end
159
+
160
+ def backup_project
161
+ # remove backup dir
162
+ run "rm -fr #{backup_path}"
163
+
164
+ output = run "cd #{tmp_path}/test_generator && bundle exec rake backup:backup"
165
+ expect(output).to_not match /\[warn\]/
166
+ expect(output).to_not match /\[error\]/
167
+ end
168
+ end
metadata ADDED
@@ -0,0 +1,159 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: backup-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Oleg Bavaev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-01-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: backup
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 3.4.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 3.4.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: whenever
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: dotenv-rails
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: fog
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.9'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.9'
69
+ - !ruby/object:Gem::Dependency
70
+ name: net-ssh
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: 2.3.0
76
+ - - <=
77
+ - !ruby/object:Gem::Version
78
+ version: 2.5.2
79
+ type: :runtime
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: 2.3.0
86
+ - - <=
87
+ - !ruby/object:Gem::Version
88
+ version: 2.5.2
89
+ - !ruby/object:Gem::Dependency
90
+ name: excon
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ~>
94
+ - !ruby/object:Gem::Version
95
+ version: 0.17.0
96
+ type: :runtime
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ~>
101
+ - !ruby/object:Gem::Version
102
+ version: 0.17.0
103
+ description: Backup rails project with backup & whenever gems
104
+ email:
105
+ - jesoba7@gmail.com
106
+ executables:
107
+ - backup_rails
108
+ extensions: []
109
+ extra_rdoc_files: []
110
+ files:
111
+ - .gitignore
112
+ - .rspec
113
+ - Gemfile
114
+ - Guardfile
115
+ - LICENSE
116
+ - README.md
117
+ - Rakefile
118
+ - backup-rails.gemspec
119
+ - bin/backup_rails
120
+ - lib/backup-rails.rb
121
+ - lib/backup-rails/version.rb
122
+ - lib/generators/backup/rails/install_generator.rb
123
+ - lib/generators/backup/rails/templates/general.rb
124
+ - lib/generators/backup/rails/templates/schedule.rb
125
+ - lib/tasks/backup.rake
126
+ - spec/bin/prepare_for_testing.rb
127
+ - spec/lib/generators/backup/rails/install_generator_spec.rb
128
+ - spec/spec_helper.rb
129
+ - spec/support/custom_matchers.rb
130
+ homepage: https://github.com/jesson/backup-rails
131
+ licenses:
132
+ - MIT
133
+ metadata: {}
134
+ post_install_message:
135
+ rdoc_options: []
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ! '>='
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ required_rubygems_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ! '>='
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ requirements: []
149
+ rubyforge_project:
150
+ rubygems_version: 2.2.1
151
+ signing_key:
152
+ specification_version: 4
153
+ summary: Backup rails project
154
+ test_files:
155
+ - spec/bin/prepare_for_testing.rb
156
+ - spec/lib/generators/backup/rails/install_generator_spec.rb
157
+ - spec/spec_helper.rb
158
+ - spec/support/custom_matchers.rb
159
+ has_rdoc: