capistrano-mongo-sync 0.1.4 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 933c334709a5c306b67c966dc4568e9b19d08985
4
- data.tar.gz: 587bbed62e4b4569e138c297b3b7425fe67e8d7a
2
+ SHA256:
3
+ metadata.gz: 0f8dd6e66c59528341b95db1601e6d5ed1e9003628ab675d0ed8a19f39b00b20
4
+ data.tar.gz: bced25f1f251ab2aa23897cc0cb1571e61b1897f105e67565bbdd95b68ca1304
5
5
  SHA512:
6
- metadata.gz: c48627b33a655b8921edc1874e2c9f48e92ce31cf5693b11ba5f1ca9552c5e3ca35c5c1d02566aef6669c8b870c8647acdaf3925da451e48eaac421d46a47a2a
7
- data.tar.gz: 720a51a7c10253eebaf6c000c61d9d043f186c5961c768929ceb5381c5b8e478d3477385a091d3f0495271f661a4bfd35a99dda5abf5f632a98937cc44c79ac9
6
+ metadata.gz: d6d7c9bca76a43f706947f585d407210080f68dff2d4c3dc7122832b7bd51c382cd6cda73768f97f3d2cca30b8481dbc3301805a7eedc3968428bbc23f7970a2
7
+ data.tar.gz: a45416c9fd270069861d19c339b0ec5cd8815d0822da5aca48a32d60e8c114f3ff1925a95e1b83c37cdf5126d5cda4b4dc359110f66f64bb5256cce32a0e2264
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ # 0.1.6
2
+
3
+ Add IDS feature used in conjunction with COLLECTION feature
4
+
1
5
  # 0.1.0
2
6
 
3
7
  Initial release
data/Gemfile.lock CHANGED
@@ -1,27 +1,32 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- capistrano-mongo-sync (0.1.0)
4
+ capistrano-mongo-sync (0.1.6)
5
5
  capistrano (~> 3.1)
6
6
  sshkit (~> 1.2)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- capistrano (3.4.0)
11
+ airbrussh (1.3.0)
12
+ sshkit (>= 1.6.1, != 1.7.0)
13
+ capistrano (3.10.1)
14
+ airbrussh (>= 1.0.0)
12
15
  i18n
13
16
  rake (>= 10.0.0)
14
- sshkit (~> 1.3)
15
- i18n (0.7.0)
17
+ sshkit (>= 1.9.0)
18
+ concurrent-ruby (1.0.5)
19
+ i18n (0.9.1)
20
+ concurrent-ruby (~> 1.0)
16
21
  metaclass (0.0.4)
17
22
  minitest (5.8.4)
18
23
  mocha (1.1.0)
19
24
  metaclass (~> 0.0.1)
20
25
  net-scp (1.2.1)
21
26
  net-ssh (>= 2.6.5)
22
- net-ssh (3.0.2)
23
- rake (11.1.1)
24
- sshkit (1.9.0)
27
+ net-ssh (4.2.0)
28
+ rake (12.3.0)
29
+ sshkit (1.15.1)
25
30
  net-scp (>= 1.1.2)
26
31
  net-ssh (>= 2.8.0)
27
32
 
@@ -34,4 +39,4 @@ DEPENDENCIES
34
39
  mocha (~> 1.1)
35
40
 
36
41
  BUNDLED WITH
37
- 1.11.2
42
+ 1.16.1
data/README.md CHANGED
@@ -13,6 +13,12 @@ Or sync just one collection from the database:
13
13
  COLLECTION=users cap production mongo:pull
14
14
  ```
15
15
 
16
+ Or sync some records (comma separated list of mongo id's) from one collection from the database:
17
+
18
+ ```ruby
19
+ COLLECTION=users IDS=1,2,3,4 cap production mongo:pull
20
+ ```
21
+
16
22
  Or sync your staging database from your production database.
17
23
 
18
24
  ```ruby
data/RELEASE.md ADDED
@@ -0,0 +1,6 @@
1
+ # Release a new version of this gem
2
+
3
+ http://guides.rubygems.org/make-your-own-gem/
4
+
5
+ `gem build capistrano-mongo-sync.gemspec`
6
+ `gem push capistrano-mongo-sync-<VERSION>.gem`
@@ -1,11 +1,11 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.name = 'capistrano-mongo-sync'
3
- gem.version = '0.1.4'
4
- gem.date = '2016-06-13'
3
+ gem.version = '0.1.6'
4
+ gem.date = '2018-01-18'
5
5
  gem.summary = "A tool for keeping local mongo in sync with remote"
6
6
  gem.description = "A tool for keeping local mongo in sync with remote"
7
- gem.authors = ["Open Listings Engineering"]
8
- gem.email = 'engineering@openlistinggem.com'
7
+ gem.authors = ["Open Listings Engineering", "We're hiring!"]
8
+ gem.email = 'engineering@openlistings.com'
9
9
  gem.homepage = 'https://github.com/openlistings/capistrano-mongo-sync'
10
10
  gem.license = 'MIT'
11
11
 
@@ -1,3 +1,5 @@
1
+ require 'digest'
2
+
1
3
  class MongoSync
2
4
  def initialize(connection)
3
5
  @connection = connection
@@ -8,6 +10,7 @@ class MongoSync
8
10
  @staging_db = fetch(:staging_db)
9
11
  @from_db = fetch(:from_db)
10
12
  @collection = fetch(:collection) || 'full'
13
+ @collection_ids = fetch(:collection_ids)
11
14
  @hipchat_client = fetch(:hipchat_client)
12
15
 
13
16
  fail "Incomplete configuration: missing remote_dump_base" unless @remote_dump_base
@@ -15,11 +18,18 @@ class MongoSync
15
18
  fail "Incomplete configuration: missing production_db" unless @production_db
16
19
  fail "Incomplete configuration: missing development_db" unless @development_db
17
20
  fail "Incomplete configuration: missing from_db" unless @from_db
21
+ fail "Incomplete configuration: missing collection" if @collection_ids && @collection.nil?
18
22
  end
19
23
 
20
24
  # the first part of the dump dir, without the timestamp... for example "mydatabase-full"
21
25
  def dump_dir_part
22
- [@from_db, @collection].join('-')
26
+ str = [@from_db, @collection].join('-')
27
+
28
+ if @collection_ids
29
+ str = [str, Digest::MD5.hexdigest(@collection_ids)].join('-')
30
+ end
31
+
32
+ str
23
33
  end
24
34
 
25
35
  ## Remote
@@ -40,12 +50,17 @@ class MongoSync
40
50
 
41
51
  args = ['-d', @from_db, '-o', File.join(@remote_dump_base, dump_dir)]
42
52
  args += ['-c', @collection] unless 'full' == @collection
53
+ args += ['-q', collection_ids_arg] if @collection_ids
43
54
 
44
55
  @connection.execute :mongodump, *args
45
56
 
46
57
  dump_dir
47
58
  end
48
59
 
60
+ def collection_ids_arg
61
+ '{_id: {$in: [%s]}}' % @collection_ids.split(',').map{|id| 'ObjectId("%s")' % id}.join(',')
62
+ end
63
+
49
64
  def staging_mongorestore!( remote_dump_dir )
50
65
  full_path_to_remote_dump_dir = if remote_dump_dir == File.basename(remote_dump_dir)
51
66
  File.join(@remote_dump_base, remote_dump_dir, @production_db)
@@ -53,7 +68,10 @@ class MongoSync
53
68
  remote_dump_dir
54
69
  end
55
70
 
56
- @connection.execute :mongorestore, '--drop', '-d', @staging_db, full_path_to_remote_dump_dir
71
+ args = []
72
+ args << '--drop' if drop_collection?
73
+ args += ['-d', @staging_db, full_path_to_remote_dump_dir]
74
+ @connection.execute :mongorestore, *args
57
75
  end
58
76
 
59
77
  def last_remote_dump
@@ -144,10 +162,18 @@ class MongoSync
144
162
  def local_mongorestore!(local_dump_dir)
145
163
  db_dump_path = File.join local_dump_dir, @from_db
146
164
  @connection.within( @local_dump_base ) do
147
- @connection.execute :mongorestore, '--drop', '-d', @development_db, db_dump_path
165
+ args = []
166
+ args << '--drop' if drop_collection?
167
+ args += ['-d', @development_db, db_dump_path]
168
+ @connection.execute :mongorestore, *args
148
169
  end
149
170
  end
150
171
 
172
+ # don't drop the collection if it's importing partially
173
+ def drop_collection?
174
+ @collection_ids.nil?
175
+ end
176
+
151
177
  ## Hipchat
152
178
  def hipchat_notify!( room, user, msg, opts = {} )
153
179
  return unless @hipchat_client
@@ -2,12 +2,14 @@
2
2
  # Usage:
3
3
  # ./bin/cap production mongo:pull
4
4
  # COLLECTION=agents ./bin/cap production mongo:pull
5
+ # COLLECTION=agents IDS=1,2,3 ./bin/cap production mongo:pull
5
6
  # ./bin/cap production mongo:sync_prod_to_staging
6
7
 
7
8
  namespace :mongo do
8
9
  set :remote_dump_base, '/tmp/dumps'
9
10
  set :local_dump_base, '/tmp/dumps'
10
11
  set :collection, ENV['COLLECTION'] || 'full'
12
+ set :collection_ids, ENV['IDS']
11
13
 
12
14
  task :sync_prod_to_staging do
13
15
  set :from_db, fetch(:production_db)
@@ -13,6 +13,7 @@ class MongoSync
13
13
  @from_db = 'mydb'.freeze
14
14
  @hipchat_client = nil
15
15
  @collection = 'full'
16
+ @collection_ids = nil
16
17
 
17
18
  instance_variable_get("@#{x}")
18
19
  end
@@ -62,6 +63,16 @@ class MongoSyncTest < Minitest::Test
62
63
  assert_equal 'mydb-agents-2015-01-01-01-01', output_dir
63
64
  end
64
65
 
66
+ def test_remote_mongodump_agents_collection_with_collection_ids
67
+ @mongo_sync.instance_variable_set("@collection", 'agents')
68
+ @mongo_sync.instance_variable_set("@collection_ids", '1,2,3')
69
+ @connection.expects(:execute).once().with(:mongodump, '-d', 'mydb', '-o', '/mnt/tmp/dumps/mydb-agents-55b84a9d317184fe61224bfb4a060fb0-2015-01-01-01-01', '-c', 'agents', '-q', '{_id: {$in: [ObjectId("1"),ObjectId("2"),ObjectId("3")]}}')
70
+ output_dir = @mongo_sync.remote_mongodump!
71
+
72
+ # path includes hexdigest of IDS string
73
+ assert_equal 'mydb-agents-55b84a9d317184fe61224bfb4a060fb0-2015-01-01-01-01', output_dir
74
+ end
75
+
65
76
  def test_dump_prompt_message
66
77
  path_to_tgz = '/tmp/dumps/mydb-full-2015-01-01-01-00.tgz'
67
78
  expected_msg = "Use local dump from today at 01:00 AM? \"%s\"? (y/n)" % path_to_tgz
@@ -104,7 +115,7 @@ class MongoSyncTest < Minitest::Test
104
115
  def test_last_remote_dump_no_dumps
105
116
  @connection.expects(:test, 'ls -td /mnt/tmp/dumps/*/mydb').returns(false)
106
117
  lrd = @mongo_sync.last_remote_dump
107
- assert_equal nil, lrd
118
+ assert_nil lrd
108
119
  end
109
120
 
110
121
  def test_last_remote_dump_dumps_y
@@ -126,19 +137,19 @@ class MongoSyncTest < Minitest::Test
126
137
  @mongo_sync.instance_variable_set '@use_remote_dump_dir', 'n'
127
138
 
128
139
  lrd = @mongo_sync.last_remote_dump
129
- assert_equal nil, lrd
140
+ assert_nil lrd
130
141
  end
131
142
 
132
143
  def test_last_local_dump_no_dumps
133
144
  @connection.expects(:test, 'ls -td /mnt/tmp/dumps/mydb-full*/mydb').returns(false)
134
145
  lrd = @mongo_sync.last_remote_dump
135
- assert_equal nil, lrd
146
+ assert_nil lrd
136
147
  end
137
148
 
138
149
  def test_last_remote_dump_tgz
139
150
  @connection.expects(:test, 'ls -td /mnt/tmp/dumps/mydb-full*/mydb').returns(false)
140
151
  lrd = @mongo_sync.last_remote_dump
141
- assert_equal nil, lrd
152
+ assert_nil lrd
142
153
  end
143
154
 
144
155
  def test_local_mongorestore
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capistrano-mongo-sync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Open Listings Engineering
8
+ - We're hiring!
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2016-06-13 00:00:00.000000000 Z
12
+ date: 2018-01-18 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: capistrano
@@ -67,7 +68,7 @@ dependencies:
67
68
  - !ruby/object:Gem::Version
68
69
  version: '1.1'
69
70
  description: A tool for keeping local mongo in sync with remote
70
- email: engineering@openlistinggem.com
71
+ email: engineering@openlistings.com
71
72
  executables: []
72
73
  extensions: []
73
74
  extra_rdoc_files: []
@@ -78,10 +79,10 @@ files:
78
79
  - Gemfile.lock
79
80
  - LICENSE
80
81
  - README.md
82
+ - RELEASE.md
81
83
  - Rakefile
82
84
  - capistrano-mongo-sync.gemspec
83
85
  - lib/capistrano/mongo-sync.rb
84
- - lib/capistrano/mongo-sync/mongo-sync.cap
85
86
  - lib/capistrano/mongo_sync/mongo_sync.rb
86
87
  - lib/capistrano/tasks/mongo-sync.cap
87
88
  - test/test_mongo_sync.rb
@@ -105,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
105
106
  version: '0'
106
107
  requirements: []
107
108
  rubyforge_project:
108
- rubygems_version: 2.5.1
109
+ rubygems_version: 2.7.3
109
110
  signing_key:
110
111
  specification_version: 4
111
112
  summary: A tool for keeping local mongo in sync with remote
@@ -1,75 +0,0 @@
1
- ##
2
- # Usage:
3
- # ./bin/cap production mongo:pull
4
- # COLLECTION=agents ./bin/cap production mongo:pull
5
- # ./bin/cap production mongo:sync_prod_to_staging
6
-
7
- namespace :mongo do
8
- set :remote_dump_base, '/tmp/dumps'
9
- set :local_dump_base, '/tmp/dumps'
10
- set :collection, ENV['COLLECTION'] || 'full'
11
-
12
- task :sync_prod_to_staging do
13
- set :from_db, fetch(:production_db)
14
-
15
- on roles(:db) do
16
- ms_remote = MongoSync.new(self)
17
- ms_remote.hipchat_notify! 'Engineering', 'capistrano', 'Started syncing prod to staging...', color: 'yellow'
18
- ms_remote.remote_setup!
19
- ms_remote.remote_cleanup!
20
-
21
- remote_dump_dir = ms_remote.last_remote_dump
22
- remote_dump_dir ||= ms_remote.remote_mongodump!
23
-
24
- ms_remote.staging_mongorestore! remote_dump_dir
25
- ms_remote.hipchat_notify! 'Engineering', 'capistrano', 'Finished syncing prod to staging...', color: 'green'
26
- end
27
- end
28
-
29
- task :pull do
30
- set :from_db, :production == fetch(:stage) ? fetch(:production_db) : fetch(:staging_db)
31
-
32
- run_locally do
33
- ms_local = MongoSync.new(self)
34
- ms_local.local_setup!
35
- ms_local.local_cleanup!
36
-
37
- # variable scope
38
- remote_tgz = nil
39
- local_tgz = nil
40
-
41
- if local_tgz = ms_local.last_local_dump
42
- # use local tgz
43
- ms_local.local_unarchive! local_tgz
44
-
45
- local_dump_dir = File.join fetch(:local_dump_base), File.basename(local_tgz, '.tgz')
46
- ms_local.local_mongorestore!(local_dump_dir)
47
- else
48
- # get dump from remote
49
- on roles(:db) do
50
- ms_remote = MongoSync.new(self)
51
- ms_remote.remote_setup!
52
- ms_remote.remote_cleanup!
53
-
54
- # find & choose tarfile or dump & archive
55
- remote_tgz = ms_remote.last_remote_dump_tgz
56
- unless remote_tgz
57
- dump_dir = ms_remote.remote_mongodump!
58
- remote_tgz = ms_remote.remote_archive! dump_dir
59
- end
60
-
61
- # download!
62
- local_tgz = File.join fetch(:local_dump_base), File.basename(remote_tgz)
63
- download! remote_tgz, local_tgz, method: :scp
64
- end
65
-
66
- # unarchive!
67
- ms_local.local_unarchive!(local_tgz)
68
-
69
- # restore!
70
- local_dump_dir = File.join fetch(:local_dump_base), File.basename(remote_tgz, '.tgz')
71
- ms_local.local_mongorestore!(local_dump_dir)
72
- end
73
- end
74
- end
75
- end