cap_sync 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +12 -32
- data/cap_sync.gemspec +2 -2
- data/lib/cap_sync/capistrano.rb +14 -0
- data/lib/cap_sync/data.rb +45 -0
- data/lib/cap_sync/db.rb +79 -0
- metadata +8 -8
- data/lib/cap_sync.rb +0 -81
data/README.rdoc
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
= Capistrano Sync Recipes
|
1
|
+
= Capistrano Db & Data Sync Recipes
|
2
2
|
|
3
3
|
Recipes to clone database & public data from production server to developement machine.
|
4
4
|
|
@@ -7,51 +7,31 @@ Recipes to clone database & public data from production server to developement m
|
|
7
7
|
Add this to your Gemfile
|
8
8
|
|
9
9
|
group :development do
|
10
|
-
gem 'cap_sync'
|
10
|
+
gem 'cap_sync'
|
11
11
|
end
|
12
12
|
|
13
|
-
Add following line to your
|
13
|
+
Add following line to your deploy.rb:
|
14
14
|
|
15
|
-
require 'cap_sync'
|
15
|
+
require 'cap_sync/capistrano'
|
16
16
|
|
17
17
|
= Syncing database
|
18
18
|
|
19
|
-
> cap sync:db
|
19
|
+
> bundle exec cap sync:db
|
20
20
|
|
21
|
-
|
22
|
-
1. Accesses production server.
|
23
|
-
2. Dumps database to app's tmp.
|
24
|
-
3. Downloads dump to local app's tmp.
|
25
|
-
4. Imports dump to local app's development database.
|
21
|
+
See lib/cap_sync/db.rb for list of available options.
|
26
22
|
|
27
|
-
|
28
|
-
|
29
|
-
Available variables and defaults:
|
30
|
-
:sync_local_env => 'development', # Local environment key in database.yml
|
31
|
-
:sync_remote_env => 'production', # Remote environment key in database.yml
|
32
|
-
:sync_remote_dump_cmd => 'mysqldump', # Remote mysqldump command
|
33
|
-
:sync_local_load_cmd => 'mysql', # Local mysqldump command
|
34
|
-
:sync_keep_dumps => false, # Keep downloaded dump in app's tmp after syncing
|
35
|
-
|
36
|
-
You can modify it in your deploy.rb as follows:
|
37
|
-
|
38
|
-
set :sync_local_cmd, '/usr/local/bin/mysql/bin'
|
23
|
+
You can set: local & remote environment, mysql dump/client command & flags, turn compression on/off, etc.
|
39
24
|
|
40
25
|
= Syncing data
|
41
26
|
|
42
|
-
> cap sync:data
|
27
|
+
> bundle exec cap sync:data
|
43
28
|
|
44
|
-
Rsync's local and remote folders. By default, does incremental implicit synchronization.
|
29
|
+
Rsync's local and remote folders. By default, does incremental implicit synchronization with rsync.
|
45
30
|
|
46
|
-
|
47
|
-
:sync_method => :rsync, # :rsync - sync with rsync, :cap - sync with capistrano
|
48
|
-
:sync_folders => {"#{shared_path}/system" => "public/system"}, # Folders to sync remote => local
|
49
|
-
:rsync_cmd => "rsync", # rsync command
|
50
|
-
:rsync_flags => "-rv --stats --delete" # rsync flags
|
31
|
+
See lib/cap_sync/data.rb for list of available options.
|
51
32
|
|
52
33
|
= Todo
|
53
34
|
|
54
35
|
1. Correctly handle multiple servers (database).
|
55
|
-
2.
|
56
|
-
3.
|
57
|
-
4. Sync up and down.
|
36
|
+
2. Envflags to modify options on the fly.
|
37
|
+
3. Win32 compability.
|
data/cap_sync.gemspec
CHANGED
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "cap_sync"
|
6
|
-
s.version = '0.0.
|
6
|
+
s.version = '0.0.8'
|
7
7
|
s.platform = Gem::Platform::RUBY
|
8
8
|
s.author = "Victor Sokolov"
|
9
9
|
s.email = "gzigzigzeo@gmail.com"
|
@@ -15,4 +15,4 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
16
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
17
|
s.require_path = 'lib'
|
18
|
-
end
|
18
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
configuration = Capistrano::Configuration.respond_to?(:instance) ?
|
4
|
+
Capistrano::Configuration.instance(:must_exist) :
|
5
|
+
Capistrano.configuration(:must_exist)
|
6
|
+
|
7
|
+
configuration.load do
|
8
|
+
|
9
|
+
_cset(:app_name) { abort('Set the application name before loading "cap_sync"') }
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'cap_sync/db'
|
14
|
+
require 'cap_sync/data'
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
configuration = Capistrano::Configuration.respond_to?(:instance) ?
|
4
|
+
Capistrano::Configuration.instance(:must_exist) :
|
5
|
+
Capistrano.configuration(:must_exist)
|
6
|
+
|
7
|
+
configuration.load do
|
8
|
+
|
9
|
+
_cset(:sync_folders, {"#{shared_path}/system" => "public/system"})
|
10
|
+
_cset(:sync_rsync_cmd, "rsync -rv --stats --delete --compress --skip-compress=jpg,gif,png,mp4")
|
11
|
+
|
12
|
+
# :sync for rsync, :cap for capistrano (used when rsync is not installed remotely)
|
13
|
+
_cset(:sync_method, :rsync)
|
14
|
+
|
15
|
+
namespace :sync do
|
16
|
+
desc "Sync remote production data with local development machine"
|
17
|
+
task :data do
|
18
|
+
folders_to_sync = sync_folders
|
19
|
+
|
20
|
+
if sync_method == :rsync
|
21
|
+
folders_to_sync.each do |remote, local|
|
22
|
+
host = find_servers(:roles => :web).first.host
|
23
|
+
system("#{sync_rsync_cmd} #{user}@#{host}:#{remote}/. #{local}")
|
24
|
+
end
|
25
|
+
elsif sync_method == :cap
|
26
|
+
folders_to_sync.each do |remote, local|
|
27
|
+
::FileUtils.rm_rf(local, :verbose => true)
|
28
|
+
download(remote, local, :recursive => true) do |event, downloader, *args|
|
29
|
+
case event
|
30
|
+
when :close then
|
31
|
+
puts "finished with #{args[0].remote}"
|
32
|
+
when :mkdir then
|
33
|
+
puts "creating directory #{args[0]}"
|
34
|
+
when :finish then
|
35
|
+
puts "all done!"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
else
|
40
|
+
raise ArgumentError, "Unknown sync method: should be :cap or :sync"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
data/lib/cap_sync/db.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
configuration = Capistrano::Configuration.respond_to?(:instance) ?
|
6
|
+
Capistrano::Configuration.instance(:must_exist) :
|
7
|
+
Capistrano.configuration(:must_exist)
|
8
|
+
|
9
|
+
configuration.load do
|
10
|
+
|
11
|
+
_cset(:sync_local_env, 'development')
|
12
|
+
_cset(:sync_remote_env, 'production')
|
13
|
+
_cset(:sync_local_load_cmd, 'mysql')
|
14
|
+
_cset(:sync_remote_dump_cmd, 'mysqldump')
|
15
|
+
_cset(:sync_local_tmp_path, 'tmp')
|
16
|
+
_cset(:sync_remote_tmp_path, "#{shared_path}/tmp")
|
17
|
+
_cset(:sync_local_keep_dumps, false)
|
18
|
+
_cset(:sync_remote_keep_dumps, false)
|
19
|
+
_cset(:sync_compress, true)
|
20
|
+
_cset(:sync_compress_cmd, 'gzip -c') # gzip -c #{dump} #{gzipped_dump}
|
21
|
+
|
22
|
+
# File should be kept after decompression if local_keep_dumps is on
|
23
|
+
_cset(:sync_uncompress_cmd, 'gunzip -c') # gunzip -c #{gzipped_dump} > #{dump}
|
24
|
+
|
25
|
+
namespace :sync do
|
26
|
+
desc "Sync remote production database with local development database"
|
27
|
+
task :db do
|
28
|
+
# Get the dump of remote database
|
29
|
+
username, password, database, host, port = remote_database_config(sync_remote_env)
|
30
|
+
dump = "sync-#{Time.now.to_i}.sql"
|
31
|
+
run "#{sync_remote_dump_cmd} -u #{username} --password=\"#{password}\" -h #{host} --port #{port} #{database} > #{sync_remote_tmp_path}/#{dump}"
|
32
|
+
|
33
|
+
# Compress and download it
|
34
|
+
if sync_compress
|
35
|
+
run "#{sync_compress_cmd} #{sync_remote_tmp_path}/#{dump} > #{sync_remote_tmp_path}/#{dump}.gz"
|
36
|
+
get "#{sync_remote_tmp_path}/#{dump}.gz", "#{sync_local_tmp_path}/#{dump}.gz"
|
37
|
+
system("#{sync_uncompress_cmd} -c #{sync_local_tmp_path}/#{dump}.gz > #{sync_local_tmp_path}/#{dump}")
|
38
|
+
else
|
39
|
+
get "#{sync_remote_tmp_path}/#{dump}", "#{sync_local_tmp_path}/#{dump}"
|
40
|
+
end
|
41
|
+
|
42
|
+
# Load dump into local database
|
43
|
+
username, password, database, host, port = local_database_config(sync_local_env)
|
44
|
+
system("#{sync_local_load_cmd} #{database} -u#{username} --password=\"#{password}\" < #{sync_local_tmp_path}/#{dump}")
|
45
|
+
|
46
|
+
# Remove temporary files
|
47
|
+
unless sync_local_keep_dumps
|
48
|
+
FileUtils.rm("#{sync_local_tmp_path}/#{dump}")
|
49
|
+
FileUtils.rm("#{sync_local_tmp_path}/#{dump}.gz") if sync_compress
|
50
|
+
else
|
51
|
+
# If compression is on, keeps only gzipped dump
|
52
|
+
FileUtils.rm("#{sync_local_tmp_path}/#{dump}") if sync_compress
|
53
|
+
end
|
54
|
+
|
55
|
+
unless sync_remote_keep_dumps
|
56
|
+
run "rm #{sync_remote_tmp_path}/#{dump}"
|
57
|
+
run "rm #{sync_remote_tmp_path}/#{dump}.gz" if sync_compress
|
58
|
+
else
|
59
|
+
run "rm #{sync_remote_tmp_path}/#{dump}" if sync_compress
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
def local_database_config(env)
|
67
|
+
db = File.open("config/database.yml") { |yf| YAML::load(yf) }
|
68
|
+
defaults_config(db[env.to_s])
|
69
|
+
end
|
70
|
+
|
71
|
+
def remote_database_config(env)
|
72
|
+
remote_config = capture("cat #{current_path}/config/database.yml")
|
73
|
+
db = YAML::load(remote_config)
|
74
|
+
defaults_config(db[env.to_s])
|
75
|
+
end
|
76
|
+
|
77
|
+
def defaults_config(db)
|
78
|
+
return db['username'], db['password'], db['database'], (db['host'] || '127.0.0.1'), (db['port'] || 3306)
|
79
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cap_sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 8
|
10
|
+
version: 0.0.8
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Victor Sokolov
|
@@ -15,8 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
19
|
-
default_executable:
|
18
|
+
date: 2011-12-15 00:00:00 Z
|
20
19
|
dependencies: []
|
21
20
|
|
22
21
|
description: Recipes to clone database & public data from production server to developement machine
|
@@ -33,8 +32,9 @@ files:
|
|
33
32
|
- README.rdoc
|
34
33
|
- Rakefile
|
35
34
|
- cap_sync.gemspec
|
36
|
-
- lib/cap_sync.rb
|
37
|
-
|
35
|
+
- lib/cap_sync/capistrano.rb
|
36
|
+
- lib/cap_sync/data.rb
|
37
|
+
- lib/cap_sync/db.rb
|
38
38
|
homepage: http://github.com/gzigzigzeo/cap_sync
|
39
39
|
licenses: []
|
40
40
|
|
@@ -64,7 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
64
64
|
requirements: []
|
65
65
|
|
66
66
|
rubyforge_project:
|
67
|
-
rubygems_version: 1.
|
67
|
+
rubygems_version: 1.8.10
|
68
68
|
signing_key:
|
69
69
|
specification_version: 3
|
70
70
|
summary: Recipes to clone database & public data from production server to developement machine
|
data/lib/cap_sync.rb
DELETED
@@ -1,81 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
require 'fileutils'
|
4
|
-
|
5
|
-
Capistrano::Configuration.instance(:must_exist).load do
|
6
|
-
{
|
7
|
-
:sync_local_env => 'development', # Local environment key in database.yml
|
8
|
-
:sync_remote_env => 'production', # Remote environment key in database.yml
|
9
|
-
:sync_remote_dump_cmd => 'mysqldump', # Remote mysqldump command
|
10
|
-
:sync_local_load_cmd => 'mysql', # Local mysqldump command
|
11
|
-
:sync_keep_dumps => false, # Keep downloaded dump in app's tmp after syncing
|
12
|
-
|
13
|
-
:sync_folders => {"#{shared_path}/system" => "public/system"}, # Folders to sync remote => local
|
14
|
-
:rsync_cmd => "rsync", # rsync command
|
15
|
-
:rsync_flags => "-rv --stats --delete", # rsync flags
|
16
|
-
:sync_method => :rsync # :rsync or :cap
|
17
|
-
}.each do |var, value|
|
18
|
-
self.set(var, value) unless exists?(var)
|
19
|
-
end
|
20
|
-
|
21
|
-
namespace :sync do
|
22
|
-
desc "Sync remote production database with local development machine"
|
23
|
-
task :db do
|
24
|
-
username, password, database, host, port = remote_database_config(sync_remote_env)
|
25
|
-
|
26
|
-
temp = "sync-#{Time.now.to_i}.sql"
|
27
|
-
run "#{sync_remote_dump_cmd} -u #{username} --password=\"#{password}\" -h #{host} --port #{port} #{database} > #{shared_path}/#{temp}"
|
28
|
-
get "#{shared_path}/#{temp}", "tmp/#{temp}"
|
29
|
-
|
30
|
-
username, password, database, host, port = local_database_config(sync_local_env)
|
31
|
-
|
32
|
-
system("#{sync_local_load_cmd} #{database} -u#{username} --password=\"#{password}\" < tmp/#{temp}")
|
33
|
-
FileUtils.rm("tmp/#{temp}") unless sync_keep_dumps
|
34
|
-
run "rm #{shared_path}/#{temp}"
|
35
|
-
end
|
36
|
-
|
37
|
-
desc "Sync remote production data with local development machine"
|
38
|
-
task :data do
|
39
|
-
folders_to_sync = Hash[*ENV['FOLDERS'].split(',')] unless ENV['FOLDERS'].nil?
|
40
|
-
folders_to_sync ||= sync_folders
|
41
|
-
|
42
|
-
if sync_method == :rsync
|
43
|
-
folders_to_sync.each do |remote, local|
|
44
|
-
host = find_servers(:roles => :web).first.host
|
45
|
-
system("#{rsync_cmd} #{rsync_flags} #{user}@#{host}:#{remote}/. #{local}")
|
46
|
-
end
|
47
|
-
elsif sync_method == :cap
|
48
|
-
folders_to_sync.each do |remote, local|
|
49
|
-
::FileUtils.rm_rf(local, :verbose => true)
|
50
|
-
download(remote, local, :recursive => true) do |event, downloader, *args|
|
51
|
-
case event
|
52
|
-
when :close then
|
53
|
-
puts "finished with #{args[0].remote}"
|
54
|
-
when :mkdir then
|
55
|
-
puts "creating directory #{args[0]}"
|
56
|
-
when :finish then
|
57
|
-
puts "all done!"
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
else
|
62
|
-
raise ArgumentError, "Unknown sync method: should be :cap or :sync"
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def local_database_config(env)
|
68
|
-
db = File.open("config/database.yml") { |yf| YAML::load(yf) }
|
69
|
-
defaults_config(db[env.to_s])
|
70
|
-
end
|
71
|
-
|
72
|
-
def remote_database_config(env)
|
73
|
-
remote_config = capture("cat #{current_path}/config/database.yml")
|
74
|
-
db = YAML::load(remote_config)
|
75
|
-
defaults_config(db[env.to_s])
|
76
|
-
end
|
77
|
-
|
78
|
-
def defaults_config(db)
|
79
|
-
return db['username'], db['password'], db['database'], db['host'], (db['port'] || 3306)
|
80
|
-
end
|
81
|
-
end
|