capistrano-db-mirror 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4e443f923780b4892b0ea156c2aad67642a71b51
4
+ data.tar.gz: de208192f6c409e1272ba5961115358050fa038b
5
+ SHA512:
6
+ metadata.gz: 3d46406392bf96bed93a3c80db3e6f6e951755e7a6ee4d77cf86f193989ea736e6b633bbc5163bc08a96006d710edc475b0a914f6dfd71e1620bd6408d68c883
7
+ data.tar.gz: 0d2d8f6c4032bac5298145baedda694033333ca0e277f59bbe49c3162d8ae4b0afeb68eec09abd396393c45dfbdc5ed62ac263cfa84abc9600b6494caabdf74e
@@ -0,0 +1,33 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+ /log/
12
+
13
+ ## Specific to RubyMotion:
14
+ .dat*
15
+ .repl_history
16
+ build/
17
+
18
+ ## Documentation cache and generated files:
19
+ /.yardoc/
20
+ /_yardoc/
21
+ /doc/
22
+ /rdoc/
23
+
24
+ ## Environment normalisation:
25
+ /.bundle/
26
+ /lib/bundler/man/
27
+
28
+ ## Misc
29
+ Gemfile.lock
30
+ gemfiles/*.lock
31
+ .ruby-version
32
+ .ruby-gemset
33
+ .rvmrc
@@ -0,0 +1,19 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1
7
+
8
+ env:
9
+ global:
10
+ - CODECLIMATE_REPO_TOKEN=0aa39b8485a9dd2aa62dbb77b02c90d1b58fa8f62a2dc03f26a304993b5908ae
11
+ matrix:
12
+ -
13
+ - CAP_VERSION=3.0
14
+
15
+ script: "bundle exec rake spec"
16
+
17
+ branches:
18
+ only:
19
+ - master
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem "capistrano", "~> #{ENV['CAP_VERSION']}" if ENV['CAP_VERSION'].to_s != ''
4
+
5
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Daisuke Taniwaki
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ 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, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,62 @@
1
+ # capistrano-db-mirror
2
+
3
+ [![Gem Version][gem-image]][gem-link]
4
+ [![Dependency Status][deps-image]][deps-link]
5
+ [![Build Status][build-image]][build-link]
6
+ [![Coverage Status][cov-image]][cov-link]
7
+ [![Code Climate][gpa-image]][gpa-link]
8
+
9
+ Mirror DB from Remote.
10
+
11
+ ## Installation
12
+
13
+ Add the capistrano-db-mirror gem to your Gemfile.
14
+
15
+ ```ruby
16
+ gem "capistrano-db-mirror"
17
+ ```
18
+
19
+ And run `bundle install`.
20
+
21
+ ## Usage
22
+
23
+ Require `capistrano/db-mirror` in your `Capfile`.
24
+
25
+ ```ruby
26
+ require `capistrano/db-mirror`
27
+ ```
28
+
29
+ Then execute the cap task.
30
+
31
+ ```bash
32
+ $ cap [env] db:mirror
33
+ ```
34
+
35
+ Here, env is the enviornment you deploy and it can be ommited for default env.
36
+
37
+ ## Contributing
38
+
39
+ 1. Fork it
40
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
41
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
42
+ 4. Push to the branch (`git push origin my-new-feature`)
43
+ 5. Create new [Pull Request](../../pull/new/master)
44
+
45
+ ## Copyright
46
+
47
+ Copyright (c) 2014 Daisuke Taniwaki. See [LICENSE](LICENSE) for details.
48
+
49
+
50
+
51
+
52
+ [gem-image]: https://badge.fury.io/rb/capistrano-db-mirror.svg
53
+ [gem-link]: http://badge.fury.io/rb/capistrano-db-mirror
54
+ [build-image]: https://secure.travis-ci.org/kaizenplatform/capistrano-db-mirror.png
55
+ [build-link]: http://travis-ci.org/kaizenplatform/capistrano-db-mirror
56
+ [deps-image]: https://gemnasium.com/kaizenplatform/capistrano-db-mirror.svg
57
+ [deps-link]: https://gemnasium.com/kaizenplatform/capistrano-db-mirror
58
+ [cov-image]: https://codeclimate.com/github/kaizenplatform/capistrano-db-mirror/badges/coverage.svg
59
+ [cov-link]: https://codeclimate.com/github/kaizenplatform/capistrano-db-mirror
60
+ [gpa-image]: https://codeclimate.com/github/kaizenplatform/capistrano-db-mirror.png
61
+ [gpa-link]: https://codeclimate.com/github/kaizenplatform/capistrano-db-mirror
62
+
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core'
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec) do |spec|
6
+ spec.pattern = FileList['spec/**/*_spec.rb']
7
+ end
8
+ task :default => :spec
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.2
@@ -0,0 +1,21 @@
1
+ Gem::Specification.new do |gem|
2
+ gem.name = "capistrano-db-mirror"
3
+ gem.version = ::File.read(::File.expand_path('../VERSION', __FILE__)).to_s.strip
4
+ gem.platform = Gem::Platform::RUBY
5
+ gem.authors = ["Daisuke Taniwaki"]
6
+ gem.email = ["daisuketaniwaki@gmail.com"]
7
+ gem.homepage = "https://github.com/kaizenplatform/capistrano-db-mirror"
8
+ gem.summary = "Mirror DB from Remote"
9
+ gem.description = "Mirror DB from Remote"
10
+ gem.license = "MIT"
11
+
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
15
+ gem.require_paths = ['lib']
16
+
17
+ gem.add_dependency "capistrano", ">= 3.0"
18
+
19
+ gem.add_development_dependency "rake"
20
+ gem.add_development_dependency "rspec", ">= 3.0"
21
+ end
@@ -0,0 +1,26 @@
1
+ module Capistrano
2
+ module DbMirror
3
+ VERSION = ::File.read(::File.expand_path('../../VERSION', __FILE__)).to_s.strip
4
+
5
+ class << self
6
+ attr_accessor :excludes, :sanitizer
7
+
8
+ def excludes
9
+ @excludes ||= [:production]
10
+ end
11
+
12
+ def sanitizer
13
+ {
14
+ '*' => {
15
+ email: "CONCAT('user-', id, '@sanitized-email.com')"
16
+ }
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ if defined?(::Rake)
24
+ require 'rake'
25
+ Dir.glob(File.join(__dir__, 'capistrano', 'db-mirror', 'tasks', '**', '*.rake')) { |path| load path }
26
+ end
@@ -0,0 +1 @@
1
+ Dir.glob(File.join(__dir__, 'tasks', '**', '*.cap')) { |path| load path }
@@ -0,0 +1,69 @@
1
+ namespace :db do
2
+ namespace :mirror do
3
+ def load_config
4
+ c = YAML.load_file("#{Rails.root}/config/database.yml")[Rails.env] # c == config
5
+ c.symbolize_keys!
6
+ end
7
+
8
+ desc "Create database dump via mysqldump"
9
+ task :dump, [:dumpfile] => :environment do |t, args|
10
+ raise "arg :dumpfile required" if args[:dumpfile].nil?
11
+
12
+ # execute mysqldump command using database.yml credentials
13
+ c = load_config
14
+ cmds = ["mysqldump", "-u #{c[:username]}", "--password='#{c[:password]}'"]
15
+ cmds << ((c[:socket].present?)? "-S #{c[:socket]}" : "-h #{c[:host]}")
16
+ cmds.concat [c[:database], "| gzip > #{args[:dumpfile]}"]
17
+ p "writing #{args[:dumpfile]}..."
18
+ `#{cmds.join " "}`
19
+ end
20
+
21
+ desc "Load mysqldump file to local database"
22
+ task :load, [:dumpfile] => :environment do |t, args|
23
+ raise "The operation is not allowed in #{Rails.env}!!" if Capistrano::DbMirror.excludes.map(&:to_s).include?(Rails.env.to_s)
24
+ raise "arg :dumpfile does not exist: #{args[:dumpfile]}" unless File.exists? args[:dumpfile]
25
+
26
+ # execute mysql load command using local database.yml credentials
27
+ # - extrace gzip file
28
+ rawfile = args[:dumpfile].sub(/\.gz$/, "")
29
+ p rawfile
30
+ `gunzip -c #{args[:dumpfile]} > #{rawfile}`
31
+ # - load dumpfile
32
+ begin
33
+ c = load_config
34
+ cmds = ["mysql", "-u #{c[:username]}", "--password='#{c[:password]}'"]
35
+ cmds << "-S #{c[:socket]}" if c[:socket].present?
36
+ cmds << "-h #{c[:host]}" if c[:host].present?
37
+ cmds.concat [c[:database], %Q|-e "source #{rawfile}"|]
38
+ p "loading #{args[:dumpfile]} into database..."
39
+ p cmds.join " "
40
+ `#{cmds.join " "}`
41
+ ensure
42
+ `rm #{rawfile}`
43
+ end
44
+ end
45
+
46
+ desc "Sanitize db"
47
+ task sanitize: [:environment] do
48
+ raise "The operation is not allowed in #{Rails.env}!!" if Capistrano::DbMirror.excludes.map(&:to_s).include?(Rails.env.to_s)
49
+
50
+ ActiveRecord::Base.connection.tables.each do |table_name|
51
+ sets = []
52
+ wheres = []
53
+ Capistrano::DbMirror.sanitizer.select { |target, _| target == '*' || target.to_s == table_name }.each do |_, config|
54
+ config.each do |column, format|
55
+ if ActiveRecord::Base.connection.columns(table_name).map(&:name).include?(column.to_s)
56
+ sets << %|`#{column}` = #{format}|
57
+ wheres << %|`#{column}` IS NOT NULL AND `#{column}` != ""|
58
+ end
59
+ end
60
+ end
61
+ if sets.present? && wheres.present?
62
+ sql = %|UPDATE `#{table_name}` SET #{sets.join(', ')} WHERE #{wheres.join(' AND ')}|
63
+ puts "Execute: #{sql}"
64
+ ActiveRecord::Base.connection.execute sql
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,44 @@
1
+ namespace :db do
2
+ desc 'Download database dump from remote and create mirror in local database - set SKIP_SANITIZE=1 for raw production data (not recommended).'
3
+ task :mirror do
4
+ on roles(:db), primary: true do
5
+ now = Time.now.strftime "%Y%m%d-%H%M%S"
6
+ filename = "#{now}-#{rails_env}.dump.gz"
7
+
8
+ # remote - create dump file
9
+ remote_f = File.join('/tmp', filename)
10
+
11
+ # local - scp dump file from remote
12
+ local_d = './dump'
13
+ FileUtils.mkdir_p(local_d)
14
+ local_f = File.join('./dump', filename)
15
+
16
+ within current_path do
17
+ rake "db:mirror:dump[#{remote_f}]"
18
+ download! remote_f, local_f, via: :scp
19
+ execute :rm, remote_f
20
+ end
21
+
22
+ run_locally do
23
+ local_backup_f = File.join(local_d, "#{now}-local.dump.gz")
24
+ # local - create current database dump for backup
25
+ p "creating local db backup as #{local_backup_f} ..."
26
+ execute "bundle exec rake db:mirror:dump[#{local_backup_f}]"
27
+ # local - load remote dump into database
28
+ p "loading remote dump #{local_f} into database..."
29
+ execute "bundle exec rake db:mirror:load[#{local_f}]"
30
+
31
+ unless ENV['SKIP_SANITIZE'] == '1'
32
+ p "sanitizing database..."
33
+ execute "bundle exec rake db:mirror:sanitize"
34
+ else
35
+ p "skipping db sanitization..."
36
+ end
37
+
38
+ # local - remove dumps
39
+ p "removing backups except the latest local backup..."
40
+ execute "ls -1 -d #{local_d}/*.dump.gz | grep -v #{local_backup_f} | xargs rm"
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'simplecov'
3
+ require "codeclimate-test-reporter"
4
+ CodeClimate::TestReporter.start
5
+
6
+ SimpleCov.start do
7
+ add_filter 'spec/'
8
+ end
9
+
10
+ Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each {|f| require f }
11
+
12
+ RSpec.configure do |config|
13
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capistrano-db-mirror
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Daisuke Taniwaki
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: capistrano
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.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.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
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: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ description: Mirror DB from Remote
56
+ email:
57
+ - daisuketaniwaki@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".travis.yml"
64
+ - Gemfile
65
+ - LICENSE
66
+ - README.md
67
+ - Rakefile
68
+ - VERSION
69
+ - capistrano-db-mirror.gemspec
70
+ - lib/capistrano-db-mirror.rb
71
+ - lib/capistrano/db-mirror.rb
72
+ - lib/capistrano/db-mirror/tasks/db-mirror.rake
73
+ - lib/capistrano/tasks/db-mirror.cap
74
+ - spec/spec_helper.rb
75
+ homepage: https://github.com/kaizenplatform/capistrano-db-mirror
76
+ licenses:
77
+ - MIT
78
+ metadata: {}
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubyforge_project:
95
+ rubygems_version: 2.4.3
96
+ signing_key:
97
+ specification_version: 4
98
+ summary: Mirror DB from Remote
99
+ test_files:
100
+ - spec/spec_helper.rb