dbsync 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ ## 0.2.0
2
+ * Internal refactoring.
3
+ * Updated gem dependencies.
@@ -3,31 +3,36 @@
3
3
  A set of rake tasks to help you sync your production
4
4
  data with your local database for development.
5
5
 
6
- Currently only supports:
7
- * Rails
8
- * MySQL
6
+ Currently only supports MySQL. The Rake tasks are written for Rails-only,
7
+ but the Sync class can be used with ruby framework, as long as you pass in the
8
+ correct database configuration.
9
9
 
10
10
  Support for more things will happen if anybody needs it.
11
11
 
12
+
12
13
  ## Usage
13
14
 
14
15
  Add to your gemfile for the groups that will need it:
15
16
 
16
- group :development, :staging do
17
- gem 'dbsync'
18
- end
19
-
17
+ ```ruby
18
+ group :development, :staging do
19
+ gem 'dbsync'
20
+ end
21
+ ```
22
+
20
23
  Add the following to your `config/environments/development.rb`
21
24
  file. Depending on your staging setup, it may also be useful
22
25
  to you to add some `dbsync` config to your `staging.rb`
23
26
  environment file. **Note** `dbsync` will not run in production.
24
27
 
25
- config.dbsync = ActiveSupport::OrderedOptions.new
26
-
27
- config.dbsync.filename = "yourapp_production_data.dump" # The name of the remote dumpfile
28
- config.dbsync.local_dir = "#{Rails.root}/../dbsync" # The local directory to store the dump file. No trailing slash
29
- config.dbsync.remote_host = "66.123.4.567" # Remote server where the dumpfile is
30
- config.dbsync.remote_dir = "~dbsync" # The directory on the remote server where the dumpfile is
28
+ ```ruby
29
+ config.dbsync = {
30
+ :filename => "yourapp_production_data.dump", # The name of the remote dumpfile.
31
+ :local_dir => "#{Rails.root}/../dbsync", # The local directory to store the dump file.
32
+ :remote_host => "66.123.4.567", # Remote server where the dumpfile is located.
33
+ :remote_dir => "~dbsync" # The directory on the remote server where the dumpfile is.
34
+ }
35
+ ```
31
36
 
32
37
  Now just make sure you have something on the remote
33
38
  server updating that dumpfile. I recommend a cronjob:
@@ -42,18 +47,21 @@ Run `rake -T dbsync` for all of the available tasks. The
42
47
  tasks are named after `git` commands mostly, so they
43
48
  should be pretty straight-forward for those who use `git`:
44
49
 
45
- rake dbsync # Alias for dbsync:pull
46
- rake dbsync:clone # Copy the remote dump file, reset the local database, and load in the dump file
47
- rake dbsync:clone_dump # Copy the remote dump file to a local destination
48
- rake dbsync:config # Show the dbsync configuration
49
- rake dbsync:fetch # Update the local dump file from the remote source
50
- rake dbsync:merge # Merge the local dump file into the local database
51
- rake dbsync:pull # Update the local dump file, and merge it into the local database
52
- rake dbsync:reset # Drop & Create the database, then load the dump file.
53
-
50
+ ```
51
+ rake dbsync # Alias for dbsync:pull
52
+ rake dbsync:clone # Copy the remote dump file, reset the local database, and load in the dump file
53
+ rake dbsync:clone_dump # Copy the remote dump file to a local destination
54
+ rake dbsync:config # Show the dbsync configuration
55
+ rake dbsync:fetch # Update the local dump file from the remote source
56
+ rake dbsync:merge # Update the local database with the local dump file
57
+ rake dbsync:pull # Update the local dump file, and merge it into the local database
58
+ rake dbsync:reset # Drop and Create the database, then load the dump file
59
+ ```
60
+
54
61
  ### TODO
55
62
 
56
- - Specs!
63
+ - Support postgres, sqlite, and anything else.
64
+
57
65
 
58
66
  ### Copyright
59
67
 
@@ -1,27 +1,25 @@
1
- # -*- encoding: utf-8 -*-
2
1
  $:.push File.expand_path("../lib", __FILE__)
3
2
  require "dbsync/version"
4
3
 
5
- Gem::Specification.new do |gem|
6
- gem.name = "dbsync"
7
- gem.version = Dbsync::VERSION
8
- gem.authors = ["Bryan Ricker"]
9
- gem.email = ["bricker88@gmail.com"]
10
- gem.description = %q{A set of rake tasks to help you sync your remote production data with your local database for development.}
11
- gem.summary = %q{Easy syncing from remote to development database in Rails.}
12
- gem.homepage = "http://github.com/bricker/dbsync"
4
+ Gem::Specification.new do |s|
5
+ s.name = "dbsync"
6
+ s.version = Dbsync::VERSION
7
+ s.authors = ["Bryan Ricker"]
8
+ s.email = ["bricker88@gmail.com"]
9
+ s.homepage = "https://github.com/bricker/dbsync"
10
+ s.license = 'MIT'
11
+ s.description = "A set of rake tasks to help you sync your remote " \
12
+ "production data with your local database for development."
13
+ s.summary = "Easy syncing from remote to development database in Rails."
13
14
 
14
- gem.rubyforge_project = "dbsync"
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib", "lib/tasks"]
15
19
 
16
- gem.files = `git ls-files`.split("\n")
17
- gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
- gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
- gem.require_paths = ["lib", "lib/tasks"]
20
-
21
- # specify any dependencies here; for example:
22
- # s.add_development_dependency "rspec"
23
- gem.add_runtime_dependency "activesupport", ">= 3.2.8"
24
- gem.add_runtime_dependency "activerecord", ">= 3.2.8"
25
- gem.add_runtime_dependency "railties", ">= 3.2.8"
20
+ s.add_dependency "activerecord", [">= 3.2.8", "< 5"]
21
+ s.add_dependency "railties", [">= 3.2.8", "< 5"]
22
+ s.add_dependency "cocaine", "~> 0.5.3"
26
23
 
24
+ s.add_development_dependency "rspec"
27
25
  end
@@ -1,4 +1,5 @@
1
1
  require "dbsync/version"
2
+ require 'dbsync/sync'
2
3
 
3
4
  module Dbsync
4
5
  class Railtie < Rails::Railtie
@@ -0,0 +1,99 @@
1
+ require 'cocaine'
2
+
3
+ module Dbsync
4
+ class Sync
5
+ class << self
6
+ def notify(message="")
7
+ $stdout.puts "[#{Time.now.strftime('%T')}] [dbsync] #{message}"
8
+ end
9
+ end
10
+
11
+
12
+ def initialize(ssh_config, db_config, options={})
13
+ ssh_config = ssh_config.with_indifferent_access
14
+ db_config = db_config.with_indifferent_access
15
+
16
+ @verbose = !!options[:verbose]
17
+
18
+ @remote_host = ssh_config[:remote_host] || raise_missing("remote_host")
19
+ @remote_dir = ssh_config[:remote_dir] || raise_missing("remote_dir")
20
+ @local_dir = ssh_config[:local_dir] || raise_missing("local_dir")
21
+ @filename = ssh_config[:filename] || raise_missing("filename")
22
+
23
+ @db_username = db_config[:username]
24
+ @db_password = db_config[:password]
25
+ @db_host = db_config[:host]
26
+ @db_database = db_config[:database]
27
+
28
+ @remote_file = "#{@remote_host}:" + File.join(@remote_dir, @filename)
29
+ @local_file = File.expand_path(File.join(@local_dir, @filename))
30
+ end
31
+
32
+
33
+ # Update the local dump file from the remote source (using rsync).
34
+ def fetch
35
+ notify "Updating '#{@local_file}' from '#{@remote_file}' via rsync..."
36
+
37
+ line = Cocaine::CommandLine.new('rsync', '-v :remote :local')
38
+ line.run({
39
+ :remote => @remote_file,
40
+ :local => @local_file
41
+ })
42
+ end
43
+
44
+
45
+ # Update the local database with the local dump file.
46
+ def merge
47
+ notify "Dumping data from '#{@local_file}' into '#{@db_database}'..."
48
+
49
+ options = ""
50
+ options += "-u :username " if @db_username.present?
51
+ options += "-p:password " if @db_password.present?
52
+ options += "-h :host " if @db_host.present?
53
+
54
+ line = Cocaine::CommandLine.new('mysql', "#{options} :database < :local")
55
+ line.run({
56
+ :username => @db_username,
57
+ :password => @db_password,
58
+ :host => @db_host,
59
+ :database => @db_database,
60
+ :local => @local_file
61
+ })
62
+ end
63
+
64
+
65
+ # Update the local dump file, and update the local database.
66
+ def pull
67
+ fetch
68
+ merge
69
+ end
70
+
71
+
72
+ # Copy the remote dump file to a local destination.
73
+ # This does a full copy (using scp), so it will take longer than
74
+ # fetch (which uses rsync).
75
+ def clone_dump
76
+ notify "Copying '#{@remote_file}' into '#{@local_dir}' via scp..."
77
+
78
+ line = Cocaine::CommandLine.new('scp', ':remote :local_dir')
79
+ line.run({
80
+ :remote => @remote_file,
81
+ :local_dir => @local_dir
82
+ })
83
+ end
84
+
85
+
86
+ private
87
+
88
+ def raise_missing(config="")
89
+ raise "Missing Configuration: '#{config}'. " \
90
+ "See README for required config."
91
+ end
92
+
93
+ def notify(*args)
94
+ if @verbose
95
+ Sync.notify(*args)
96
+ end
97
+ end
98
+ end
99
+ end
@@ -1,3 +1,3 @@
1
1
  module Dbsync
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -2,116 +2,70 @@
2
2
 
3
3
  desc "Alias for dbsync:pull"
4
4
  task :dbsync do
5
- Rake::Task["dbsync:pull"].invoke
5
+ Rake::Task['dbsync:pull'].invoke
6
6
  end
7
7
 
8
8
  namespace :dbsync do
9
9
  task :setup => :environment do
10
- module Dbsync
11
- LOGGER = $stdout
12
- CONFIG = Rails.application.config.dbsync
13
-
14
- CONFIG['remote'] = "#{CONFIG['remote_host']}:" + File.join(CONFIG['remote_dir'], CONFIG['filename'])
15
- CONFIG['local'] = File.join CONFIG['local_dir'], CONFIG['filename']
16
- end
17
-
18
- # ---------------
19
-
20
- Dbsync::LOGGER.puts "Environment: #{Rails.env}"
21
-
10
+ Dbsync::Sync.notify "Environment: #{Rails.env}"
11
+
22
12
  if Rails.env == 'production'
23
- raise "These tasks are destructive and shouldn't be used in the production environment."
13
+ raise "These tasks are destructive and shouldn't " \
14
+ "be used in the production environment."
24
15
  end
25
16
 
26
- #-----------------
27
-
28
- if Dbsync::CONFIG['filename'].blank?
29
- raise "No dump filename specified."
30
- elsif Dbsync::CONFIG['remote'].blank?
31
- raise "No remote dump file specified."
32
- end
33
-
34
- #-----------------
35
-
36
- VERBOSE = %w{1 true}.include? ENV['VERBOSE']
37
- DB = ActiveRecord::Base.configurations[Rails.env]
17
+ @dbsync = Dbsync::Sync.new(
18
+ Rails.application.config.dbsync,
19
+ ActiveRecord::Base.configurations[Rails.env],
20
+ verbose: true
21
+ )
38
22
  end
39
-
40
- #-----------------------
41
-
23
+
24
+
42
25
  desc "Show the dbsync configuration"
43
26
  task :config => :setup do
44
- Dbsync::LOGGER.puts "Config:"
45
- Dbsync::LOGGER.puts Dbsync::CONFIG.to_yaml
27
+ # We don't use Sync.notify here because we don't want or need
28
+ # the extra output that comes with it.
29
+ $stdout.puts Rails.application.config.dbsync.to_yaml
46
30
  end
47
-
48
- #-----------------------
49
-
31
+
32
+
50
33
  desc "Update the local dump file, and merge it into the local database"
51
- task :pull => [:fetch, :merge]
52
-
53
- desc "Copy the remote dump file, reset the local database, and load in the dump file"
54
- task :clone => [:clone_dump, :reset]
55
-
56
- #-----------------------
57
-
58
- desc "Update the local dump file from the remote source"
34
+ task :pull => :setup do
35
+ @dbsync.pull
36
+ end
37
+
38
+
39
+ desc "Copy the remote dump file, reset the local database, " \
40
+ "and load in the dump file"
41
+ task :clone => :setup do
42
+ @dbsync.clone_dump
43
+ Rake::Task['dbsync:reset'].invoke
44
+ end
45
+
46
+
47
+ desc "Update the local dump file from the remote source."
59
48
  task :fetch => :setup do
60
- Dbsync::LOGGER.puts "Fetching #{Dbsync::CONFIG['remote']} using rsync"
61
- output = %x{ rsync -v #{Dbsync::CONFIG['remote']} #{Dbsync::CONFIG['local']} }
62
-
63
- if VERBOSE
64
- Dbsync::LOGGER.puts output
65
- end
66
-
67
- Dbsync::LOGGER.puts "Finished."
49
+ @dbsync.fetch
68
50
  end
69
51
 
70
- #-----------------------
71
52
 
72
53
  desc "Copy the remote dump file to a local destination"
73
54
  task :clone_dump => :setup do
74
- Dbsync::LOGGER.puts "Fetching #{Dbsync::CONFIG['remote']} using scp"
75
- output = %x{ scp #{Dbsync::CONFIG['remote']} #{Dbsync::CONFIG['local_dir']}/ }
76
-
77
- if VERBOSE
78
- Dbsync::LOGGER.puts output
79
- end
80
-
81
- Dbsync::LOGGER.puts "Finished."
55
+ @dbsync.clone_dump
82
56
  end
83
57
 
84
- #-----------------------
85
-
86
- desc "Merge the local dump file into the local database"
58
+
59
+ desc "Update the local database with the local dump file."
87
60
  task :merge => :setup do
88
- Dbsync::LOGGER.puts "Dumping data from #{Dbsync::CONFIG['local']} into #{DB['database']}"
89
-
90
- command = "mysql "
91
- command += "-u #{DB['username']} " if DB['username'].present?
92
- command += "-p#{DB['password']} " if DB['password'].present?
93
- command += "-h #{DB['host']} " if DB['host'].present?
94
- command += "#{DB['database']} < #{Dbsync::CONFIG['local']}"
95
-
96
- output = %x{#{command}}
97
-
98
- if VERBOSE
99
- Dbsync::LOGGER.puts output
100
- end
101
-
102
- Dbsync::LOGGER.puts "Finished."
61
+ @dbsync.merge
103
62
  end
104
63
 
105
- #-----------------------
106
-
107
- desc "Drop & Create the database, then load the dump file."
64
+
65
+ desc "Drop and Create the database, then load the dump file."
108
66
  task :reset => :setup do
109
- if VERBOSE
110
- Dbsync::LOGGER.puts "Resetting database..."
111
- end
112
-
113
67
  Rake::Task["db:drop"].invoke
114
68
  Rake::Task["db:create"].invoke
115
- Rake::Task["dbsync:merge"].invoke
69
+ @dbsync.merge
116
70
  end
117
71
  end
@@ -0,0 +1,5 @@
1
+ require 'bundler/setup'
2
+ Bundler.require
3
+
4
+ RSpec.configure do |config|
5
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dbsync::Sync do
4
+ let(:ssh_config) do
5
+ end
6
+
7
+ let(:db_config) do
8
+ end
9
+
10
+
11
+ describe "::notify" do
12
+ end
13
+
14
+ describe '#fetch' do
15
+ end
16
+
17
+ describe '#merge' do
18
+ end
19
+
20
+ describe '#clone_dump' do
21
+ end
22
+
23
+ describe '#pull' do
24
+ end
25
+ end
metadata CHANGED
@@ -1,57 +1,66 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dbsync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Bryan Ricker
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2013-04-03 00:00:00.000000000 Z
12
+ date: 2014-02-13 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
- name: activesupport
15
- requirement: !ruby/object:Gem::Requirement
15
+ name: activerecord
16
+ requirement: &70160586951120 !ruby/object:Gem::Requirement
17
+ none: false
16
18
  requirements:
17
19
  - - ! '>='
18
20
  - !ruby/object:Gem::Version
19
21
  version: 3.2.8
22
+ - - <
23
+ - !ruby/object:Gem::Version
24
+ version: '5'
20
25
  type: :runtime
21
26
  prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ! '>='
25
- - !ruby/object:Gem::Version
26
- version: 3.2.8
27
+ version_requirements: *70160586951120
27
28
  - !ruby/object:Gem::Dependency
28
- name: activerecord
29
- requirement: !ruby/object:Gem::Requirement
29
+ name: railties
30
+ requirement: &70160586945980 !ruby/object:Gem::Requirement
31
+ none: false
30
32
  requirements:
31
33
  - - ! '>='
32
34
  - !ruby/object:Gem::Version
33
35
  version: 3.2.8
36
+ - - <
37
+ - !ruby/object:Gem::Version
38
+ version: '5'
34
39
  type: :runtime
35
40
  prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ! '>='
39
- - !ruby/object:Gem::Version
40
- version: 3.2.8
41
+ version_requirements: *70160586945980
41
42
  - !ruby/object:Gem::Dependency
42
- name: railties
43
- requirement: !ruby/object:Gem::Requirement
43
+ name: cocaine
44
+ requirement: &70160586961540 !ruby/object:Gem::Requirement
45
+ none: false
44
46
  requirements:
45
- - - ! '>='
47
+ - - ~>
46
48
  - !ruby/object:Gem::Version
47
- version: 3.2.8
49
+ version: 0.5.3
48
50
  type: :runtime
49
51
  prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
52
+ version_requirements: *70160586961540
53
+ - !ruby/object:Gem::Dependency
54
+ name: rspec
55
+ requirement: &70160586961120 !ruby/object:Gem::Requirement
56
+ none: false
51
57
  requirements:
52
58
  - - ! '>='
53
59
  - !ruby/object:Gem::Version
54
- version: 3.2.8
60
+ version: '0'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: *70160586961120
55
64
  description: A set of rake tasks to help you sync your remote production data with
56
65
  your local database for development.
57
66
  email:
@@ -61,36 +70,44 @@ extensions: []
61
70
  extra_rdoc_files: []
62
71
  files:
63
72
  - .gitignore
73
+ - CHANGELOG.md
64
74
  - Gemfile
65
75
  - MIT-LICENSE
66
76
  - README.markdown
67
77
  - Rakefile
68
78
  - dbsync.gemspec
69
79
  - lib/dbsync.rb
80
+ - lib/dbsync/sync.rb
70
81
  - lib/dbsync/version.rb
71
82
  - lib/tasks/dbsync.rake
72
- homepage: http://github.com/bricker/dbsync
73
- licenses: []
74
- metadata: {}
83
+ - spec/spec_helper.rb
84
+ - spec/sync_spec.rb
85
+ homepage: https://github.com/bricker/dbsync
86
+ licenses:
87
+ - MIT
75
88
  post_install_message:
76
89
  rdoc_options: []
77
90
  require_paths:
78
91
  - lib
79
92
  - lib/tasks
80
93
  required_ruby_version: !ruby/object:Gem::Requirement
94
+ none: false
81
95
  requirements:
82
96
  - - ! '>='
83
97
  - !ruby/object:Gem::Version
84
98
  version: '0'
85
99
  required_rubygems_version: !ruby/object:Gem::Requirement
100
+ none: false
86
101
  requirements:
87
102
  - - ! '>='
88
103
  - !ruby/object:Gem::Version
89
104
  version: '0'
90
105
  requirements: []
91
- rubyforge_project: dbsync
92
- rubygems_version: 2.0.2
106
+ rubyforge_project:
107
+ rubygems_version: 1.8.11
93
108
  signing_key:
94
- specification_version: 4
109
+ specification_version: 3
95
110
  summary: Easy syncing from remote to development database in Rails.
96
- test_files: []
111
+ test_files:
112
+ - spec/spec_helper.rb
113
+ - spec/sync_spec.rb
checksums.yaml DELETED
@@ -1,15 +0,0 @@
1
- ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MjJhN2M5OTY4OGQ4MjE2MzY1NjU5OWEyZDMxMTVhMmYxZDZlMzUwMQ==
5
- data.tar.gz: !binary |-
6
- MWI5MWUwOTU4NGVhMjI1ZjY1OGE0MWEwYmVlYmY2ZTQ0MDcyZTM4Yg==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- MGI4MjJmYmIxNTdhZWI1M2JlNTdlMjI0ZmY5YjQyYWRjN2QyM2YzNmU4NDI5
10
- Y2UyMjhkNTZjYTIxNGVhZDI0MGZmMDNhY2RiODJiYTIwZWZmZjNmYWUzNjBj
11
- ZWVlNDEyYWQzYjA5ZGU2OTU3MDRkYTNhYzc5NTY5NzkzNmViNTQ=
12
- data.tar.gz: !binary |-
13
- YWRjOWQ4MWI0ODNhOWNmYTI1YWQ1Y2UzYjVmYTkwNGJiZmJjM2NmNWMwYjRj
14
- OTgwYTZiNDZlMjNmMDliMjFlZmRkOTEwNGIyODAxZjU4YjViMDhkNThlNzUy
15
- ODY2MGNhMjIyZjI0ZjBhNTQ5NjViOWQ5Yzk5MDEzZmQyZmRjMmM=