leipreachan 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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1617b7813e458266d6324091531da3f3099a75a2
4
+ data.tar.gz: 42c96d3a9bfd861d2d2f57211844f4802fe22f24
5
+ SHA512:
6
+ metadata.gz: 39c06b88689db722b1552d8b87e787251f065bdad11e6c66b276e370eaa8379cb47096797dd9d963ac48f5c5fd1df0931a2803a46c2f80f8ee65a6ecca7e4747
7
+ data.tar.gz: 03f812d5d96a463d9029400dd9f3f1def7b83f2c9572c165316e2d04cfa38a85f11df0f20826954b4cd779774595688383655f8f35d8e133e0e3c8b28f5d72fc
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in leipreachan.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Anadea Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,93 @@
1
+ # Leipreachan
2
+
3
+ Самый простой способ создания резервных копий базы данных проекта на сколько это вообще возможно.
4
+
5
+ ## Установка
6
+
7
+ Добавьте эту строку в ваш Gemfile:
8
+
9
+ ```ruby
10
+ gem 'leipreachan'
11
+ ```
12
+
13
+ После этого запустите:
14
+
15
+ $ bundle
16
+
17
+ Или установите вручную:
18
+
19
+ $ gem install leipreachan
20
+
21
+ ## Использование
22
+
23
+ ### Capistrano 3
24
+
25
+ Для создания резервных копий с помощью Capistrano добавьте в ваш 'Capfile' эту строку:
26
+
27
+ require 'leipreachan/capistrano3'
28
+
29
+ Это добавит следующие задачи в Capistrano:
30
+
31
+ cap deploy:leipreachan:backup # Backup database
32
+ cap deploy:leipreachan:list # List of backups
33
+ cap deploy:leipreachan:restore # Restore database
34
+
35
+ Если вы хотите создать резервную копию в процессе деплоя приложения вам необходимо добавить эту строку в 'deploy.rb':
36
+
37
+ before "deploy:migrate", "deploy:leipreachan:backup"
38
+
39
+ Резервная копия будет создана перед миграциями базы данных.
40
+
41
+ По умолчанию резервная копия создается в 'shared/backups', но если у вас есть необходимость установить свой каталог, это можно сделать с помощью переменной 'backups_folder':
42
+
43
+ set :backups_folder, '../../current'
44
+
45
+ Gem берет за основу каталог с релизом. Учтите это при установке каталога резервных копий.
46
+
47
+ Для восстановления сделанного бекапа необходимо запустить:
48
+
49
+ $ cap [environment] deploy:leipreachan:restore
50
+
51
+ ВНИМЕНИЕ!!! Восстанавливается **последняя** сделанная резервная копия.
52
+
53
+ ### Интергация в Whenever
54
+
55
+ Просто добавьте эти строки в ваш 'config/schedule.rb':
56
+
57
+ ```ruby
58
+ every 1.day, :at => '4:30 am' do
59
+ rake "leipreachan:backup"
60
+ end
61
+ ```
62
+ Так же вы можете изменить каталог, куда будут складываться резервные копии. По умолчанию они складываются в './backups', т.е. создается каталог backups в корневом каталоге приложения.
63
+
64
+ ```ruby
65
+ every 1.month, do
66
+ rake "leipreachan:backup DIR=/tmp/database_backups"
67
+ end
68
+ ```
69
+ Есть возможность указать сколько дней хранить резервные копии (обратите внимание, что эта настройка не распространяется на количество резервных копий внутри каталога дня; каждый день их может храниться неограниченное количество). По умолчанию хранится 30 каталогов, разбитых по датам.
70
+
71
+ ```ruby
72
+ every 5.days, do
73
+ rake "leipreachan:backup DAYS=5"
74
+ end
75
+ ```
76
+
77
+ ### Использование Rake задач
78
+
79
+ Для работы с резервными копиями базы данных есть неколько rake задач:
80
+
81
+ rake leipreachan:backup # Backup project database; Options: DIR=backups RAILS_ENV=production DAYS=30
82
+ rake leipreachan:list # List of all backups; Options: DATE=20150130
83
+ rake leipreachan:restore # Restore project database; Options: DIR=backups RAILS_ENV=production
84
+
85
+ leipreachan:backup - создаст резервную копию базы данных.
86
+ leipreachan:list - выведет список дней и бекапов в последнем дне.
87
+ leipreachan:restore - восстановит базу данных из резервной копии.
88
+
89
+ Опции, которые можно передать из окружения:
90
+
91
+ * DIR - каталог, куда необходимо сохранить резервную копию
92
+ * DATE - показать резервные копии на определенную дату
93
+ * DAYS - сколько дней хранить резервные копии
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ Dir.glob('lib/tasks/*.rake').each {|r| import r}
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "leipreachan"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'leipreachan/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "leipreachan"
8
+ spec.version = Leipreachan::VERSION
9
+ spec.authors = ["Anadea Inc team (http://anadea.info)"]
10
+ spec.email = ["gemmaker@anahoret.com"]
11
+
12
+ spec.summary = %q{Backup and restore your database by the simple way.}
13
+ spec.description = %q{Backup and restore your database as simple as posible.}
14
+ spec.homepage = "https://github.com/anadea/leipreachan"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "bin"
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency 'bundler', "~> 1.9"
23
+ spec.add_development_dependency 'rake', "~> 10.0"
24
+ spec.add_development_dependency 'rspec'
25
+ spec.add_development_dependency 'railties'
26
+ spec.add_development_dependency 'rails'
27
+ end
@@ -0,0 +1,42 @@
1
+ namespace :deploy do
2
+ set :folder, fetch(:backups_folder) || '../../shared/backups'
3
+ namespace :leipreachan do
4
+ desc "Backup database"
5
+ task :backup do
6
+ on roles(:app), in: :sequence, wait: 5 do
7
+ within release_path do
8
+ with rails_env: fetch(:rails_env) do
9
+ execute :bundle, :exec, :rake, "leipreachan:backup DIR=#{fetch(:folder)}"
10
+ end
11
+ end
12
+ end
13
+ end
14
+ desc "List of backups"
15
+ task :list do
16
+ on roles(:app) do
17
+ within current_path do
18
+ with rails_env: fetch(:rails_env) do
19
+ execute :bundle, :exec, :rake, "leipreachan:list DIR=#{fetch(:folder)}"
20
+ end
21
+ end
22
+ end
23
+ end
24
+ desc "Restore database"
25
+ task :restore do
26
+ on roles(:app) do
27
+ within current_path do
28
+ with rails_env: fetch(:rails_env) do
29
+ puts "="*80
30
+ puts "WARNING!!! YOUR CURRENT DATABASE DATA WILL BE LOST!!!"
31
+ puts "Think twice before enter 'YES' and push the Enter button"
32
+ puts "="*80
33
+ set :answercheck, ask('"YES" for restore last backup of the database: ', 'No')
34
+ if fetch(:answercheck) == 'YES'
35
+ execute :bundle, :exec, :rake, "leipreachan:restorelast DIR=#{fetch(:folder)}"
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1 @@
1
+ load File.expand_path('../../capistrano3/tasks/leipreachan.cap', __FILE__)
@@ -0,0 +1,13 @@
1
+ module Leipreachan
2
+ class Backuper < DBBackup
3
+ def dbbackup!
4
+ password = db_config['password'].present? ? "-p#{db_config['password']} " : ""
5
+ system("mysqldump -u#{db_config['username']} #{password}-i -c -q --single-transaction #{db_config['database']} | gzip > #{backup_file}.gz")
6
+ end
7
+
8
+ def dbrestore! file
9
+ password = db_config['password'].present? ? "-p#{db_config['password']} " : ""
10
+ system("zcat < #{backup_base_on(backup_folder)}/#{file} | mysql -u#{db_config['username']} #{password}#{db_config['database']}")
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,29 @@
1
+ module Leipreachan
2
+ class Backuper < DBBackup
3
+ def dbbackup!
4
+ username = db_config['username'].present? ? "-U #{db_config['username']}" : ""
5
+ password = db_config['password'].present? ? "PGPASSWORD='#{db_config['password']}' " : ""
6
+ system("#{password}pg_dump #{username} #{db_config['database']} | gzip > #{backup_file}.gz")
7
+ end
8
+
9
+ def dbrestore! file
10
+ username = db_config['username'].present? ? "-U #{db_config['username']}" : ""
11
+ password = db_config['password'].present? ? "PGPASSWORD='#{db_config['password']}' " : ""
12
+
13
+ puts "Will be restored -> #{file}"
14
+ puts ""
15
+ drop_pg!
16
+ system("zcat < #{backup_base_on(backup_folder)}/#{file} | #{password}psql #{username} #{db_config['database']}")
17
+ end
18
+
19
+ private
20
+
21
+ def drop_pg!
22
+ username = db_config['username'].present? ? "-U #{db_config['username']}" : ""
23
+ password = db_config['password'].present? ? "PGPASSWORD='#{db_config['password']}' " : ""
24
+ drop_table_query = "drop schema public cascade; create schema public;"
25
+
26
+ system("echo \"#{drop_table_query}\" | #{password}psql #{username} #{db_config['database']}")
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,6 @@
1
+ module Leipreachan
2
+ # require 'rails'
3
+ class Railtie < Rails::Railtie
4
+ rake_tasks { load "tasks/leipreachan.rake" }
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ module Leipreachan
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,121 @@
1
+ require 'leipreachan/version'
2
+ require 'leipreachan/railtie' if defined?(Rails)
3
+ require 'rails'
4
+ require 'active_record'
5
+
6
+ module Leipreachan
7
+ def self.get_backuper_for env
8
+ db_config = ActiveRecord::Base.configurations[Rails.env]
9
+ require "leipreachan/#{db_config['adapter']}"
10
+ Backuper.new(env)
11
+ end
12
+
13
+ class DBBackup
14
+ MAX_DAYS = 30
15
+ DIRECTORY = 'backups'
16
+
17
+ attr_accessor :max_days,
18
+ :directory,
19
+ :target_date,
20
+ :backup_folder,
21
+ :backup_file,
22
+ :base_path,
23
+ :db_config
24
+
25
+ def initialize env
26
+ @max_days = (env['DAYS'] || MAX_DAYS).to_i
27
+ @target_date = env['DATE']
28
+ @backup_folder = env['DATE'] || Time.now.strftime("%Y%m%d")
29
+ @directory = env['DIR'] || DIRECTORY
30
+ datetime_stamp = Time.now.strftime("%Y%m%d%H%M%S")
31
+ @base_path = File.join(Rails.root, directory)
32
+
33
+ file_name = "#{datetime_stamp}.sql"
34
+ @backup_file = File.join(backup_base_on(backup_folder), file_name)
35
+
36
+ @db_config = ActiveRecord::Base.configurations[Rails.env]
37
+ end
38
+
39
+ def backup!
40
+ FileUtils.mkdir_p(backup_base_on(backup_folder))
41
+ dbbackup!
42
+ puts "Created backup: #{backup_file}.gz"
43
+ backups_count = Dir.new(backup_base_on(backup_folder)).entries.select{|name| name.match(/sql.gz$/)}.size
44
+ puts "#{backups_count} backups available for #{backup_folder} date"
45
+
46
+ remove_unwanted_backups
47
+ end
48
+
49
+ def restore!
50
+ dbrestore! get_file_for_restore
51
+ end
52
+
53
+ def restorelast!
54
+ dbrestore! get_lastfile_for_restore
55
+ end
56
+
57
+ def list
58
+ target_date.present? ? single_date(target_date) : all_dates
59
+ end
60
+
61
+ private
62
+
63
+ def get_backups_list folder
64
+ Dir.new(backup_base_on(folder)).entries.select{|name| name.match(/sql.gz$/)}.sort
65
+ end
66
+
67
+ def all_dates
68
+ list = Dir.new(base_path).entries.select{|name| name.match(/\d+/)}.sort
69
+ list.first(list.size - 1).each_with_index do |folder, index|
70
+ count = get_backups_list(folder).size
71
+ puts "-> #{folder}: #{count}"
72
+ end
73
+ single_date list.last
74
+ end
75
+
76
+ def single_date date
77
+ count = get_backups_list(date).size
78
+ puts "-> #{date}: #{count}"
79
+ get_backups_list(date).each_with_index do |backup, index|
80
+ puts " #{backup}"
81
+ end
82
+ end
83
+
84
+ def backup_base_on target_date
85
+ File.join(base_path, target_date)
86
+ end
87
+
88
+ def remove_unwanted_backups
89
+ all_backups = Dir.new(base_path).entries.select{|folder| folder.match(/\d{8}/)}.sort.reverse
90
+
91
+ max_backups = (max_days if max_days > 0) || MAX_DAYS
92
+ unwanted_backups = all_backups[max_backups..-1] || []
93
+
94
+ for unwanted_backup in unwanted_backups
95
+ FileUtils.rm_rf(File.join(base_path, unwanted_backup))
96
+ end
97
+ puts "Deleted #{unwanted_backups.length} days, #{all_backups.length - unwanted_backups.length} days available"
98
+ end
99
+
100
+ def get_file_for_restore
101
+ backups_list = backup_folder_items.reverse
102
+ backups_list.each_with_index do |backup, index|
103
+ puts "#{index}. #{backup}"
104
+ end
105
+ puts "="*80
106
+ puts "WARNING!!! YOUR CURRENT DATABASE DATA WILL BE LOST!!!"
107
+ puts "Think twice before push the Enter button"
108
+ puts "="*80
109
+ puts "Enter file name to restore: [#{backups_list.last}]"
110
+ STDIN.gets.chomp.presence || backups_list.last
111
+ end
112
+
113
+ def get_lastfile_for_restore
114
+ backup_folder_items.reverse.last
115
+ end
116
+
117
+ def backup_folder_items
118
+ get_backups_list(backup_folder).reverse
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ namespace :leipreachan do
4
+ desc 'List of all backups; Options: DATE=20150130'
5
+ task list: [:environment] do
6
+ require 'leipreachan'
7
+ Leipreachan.get_backuper_for(ENV).list
8
+ end
9
+ desc 'Restore project database; Options: DIR=backups RAILS_ENV=production DAYS=30'
10
+ task restore: [:environment] do
11
+ require 'leipreachan'
12
+ Leipreachan.get_backuper_for(ENV).restore!
13
+ end
14
+ task restorelast: [:environment] do
15
+ require 'leipreachan'
16
+ Leipreachan.get_backuper_for(ENV).restorelast!
17
+ end
18
+ desc "Backup project database; Options: DIR=backups RAILS_ENV=production DAYS=30"
19
+ task backup: [:environment] do
20
+ require 'leipreachan'
21
+ Leipreachan.get_backuper_for(ENV).backup!
22
+ end
23
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: leipreachan
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Anadea Inc team (http://anadea.info)
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.9'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.9'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
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: railties
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Backup and restore your database as simple as posible.
84
+ email:
85
+ - gemmaker@anahoret.com
86
+ executables:
87
+ - console
88
+ - setup
89
+ extensions: []
90
+ extra_rdoc_files: []
91
+ files:
92
+ - ".gitignore"
93
+ - ".rspec"
94
+ - Gemfile
95
+ - LICENSE.txt
96
+ - README.md
97
+ - Rakefile
98
+ - bin/console
99
+ - bin/setup
100
+ - leipreachan.gemspec
101
+ - lib/capistrano3/tasks/leipreachan.cap
102
+ - lib/leipreachan.rb
103
+ - lib/leipreachan/capistrano3.rb
104
+ - lib/leipreachan/mysql2.rb
105
+ - lib/leipreachan/postgresql.rb
106
+ - lib/leipreachan/railtie.rb
107
+ - lib/leipreachan/version.rb
108
+ - lib/tasks/leipreachan.rake
109
+ homepage: https://github.com/anadea/leipreachan
110
+ licenses:
111
+ - MIT
112
+ metadata: {}
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubyforge_project:
129
+ rubygems_version: 2.2.2
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: Backup and restore your database by the simple way.
133
+ test_files: []