backup-rails 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: