capistrano-db-mirror 0.0.2

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.
@@ -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