Class: MongoSync

Inherits:
Object
  • Object
show all
Defined in:
lib/capistrano/mongo_sync/mongo_sync.rb

Instance Method Summary collapse

Constructor Details

#initialize(connection) ⇒ MongoSync

Returns a new instance of MongoSync.



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/capistrano/mongo_sync/mongo_sync.rb', line 4

def initialize(connection)
  @connection = connection
  @remote_dump_base = fetch(:remote_dump_base)
  @local_dump_base = fetch(:local_dump_base)
  @production_db = fetch(:production_db)
  @development_db = fetch(:development_db)
  @staging_db = fetch(:staging_db)
  @from_db = fetch(:from_db)
  @collection = fetch(:collection) || 'full'
  @collection_ids = fetch(:collection_ids)
  @hipchat_client = fetch(:hipchat_client)

  fail "Incomplete configuration: missing remote_dump_base" unless @remote_dump_base
  fail "Incomplete configuration: missing local_dump_base" unless @local_dump_base
  fail "Incomplete configuration: missing production_db" unless @production_db
  fail "Incomplete configuration: missing development_db" unless @development_db
  fail "Incomplete configuration: missing from_db" unless @from_db
  fail "Incomplete configuration: missing collection" if @collection_ids && @collection.nil?
end

Instance Method Details

#collection_ids_argObject



60
61
62
# File 'lib/capistrano/mongo_sync/mongo_sync.rb', line 60

def collection_ids_arg
  '\'{_id: {$in: [%s]}}\'' % @collection_ids.split(',').map{|id| 'ObjectId("%s")' % id}.join(',')
end

#drop_collection?Boolean

don’t drop the collection if it’s importing partially

Returns:

  • (Boolean)


173
174
175
# File 'lib/capistrano/mongo_sync/mongo_sync.rb', line 173

def drop_collection?
  @collection_ids.nil?
end

#dump_dir_partObject

the first part of the dump dir, without the timestamp… for example “mydatabase-full”



25
26
27
28
29
30
31
32
33
# File 'lib/capistrano/mongo_sync/mongo_sync.rb', line 25

def dump_dir_part
  str = [@from_db, @collection].join('-')

  if @collection_ids
    str = [str, Digest::MD5.hexdigest(@collection_ids)].join('-')
  end

  str
end

#dump_prompt(gvar, filename) ⇒ Object



202
203
204
205
206
207
208
# File 'lib/capistrano/mongo_sync/mongo_sync.rb', line 202

def dump_prompt( gvar, filename )
  return false unless filename

  until fetch(gvar) =~ /\A[yn]\Z/
    @connection.ask(gvar, dump_prompt_message(gvar, filename))
  end
end

#dump_prompt_message(gvar, filename) ⇒ Object

Utility



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/capistrano/mongo_sync/mongo_sync.rb', line 184

def dump_prompt_message( gvar, filename )
  dump_tstamp = filename[/(\d{4}-\d{2}-\d{2}-\d{2}-\d{2})/, 1]
  dump_time = Time.new(*dump_tstamp.split('-'))

  fmt = if dump_time.strftime('%D') == Time.now.strftime('%D')
    'today at %I:%M %p'
  elsif dump_time.strftime('%D') == (Time.now - 24 * 60 * 60).strftime('%D')
    'yesterday at %I:%M %p'
  else
    '%B %d, %Y at %I:%M %p'
  end

  dump_time_human = dump_time.strftime(fmt)

  local_remote = gvar.to_s =~ /local/ ? 'local' : 'remote'
  'Use %s dump from %s? "%s"? (y/n)' % [local_remote, dump_time_human, filename]
end

#hipchat_notify!(room, user, msg, opts = {}) ⇒ Object

Hipchat



178
179
180
181
# File 'lib/capistrano/mongo_sync/mongo_sync.rb', line 178

def hipchat_notify!( room, user, msg, opts = {} )
  return unless @hipchat_client
  @hipchat_client[room].send(user, msg, opts)
end

#last_local_dumpObject



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/capistrano/mongo_sync/mongo_sync.rb', line 133

def last_local_dump
  pattern = File.join(@local_dump_base, '%s*.tgz' % dump_dir_part)

  if @connection.test "ls #{pattern}"
    local_dump_candidate = @connection.capture(:ls, '-td', pattern).split("\n")[0]

    dump_prompt(:use_local_dump, local_dump_candidate)

    if 'y' == fetch(:use_local_dump)
      local_dump_candidate
    else
      nil
    end
  else
    nil
  end
end

#last_remote_dumpObject



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/capistrano/mongo_sync/mongo_sync.rb', line 77

def last_remote_dump
  previous_remote_dump_dirs_wildcard = File.join @remote_dump_base, '%s*/%s' % [dump_dir_part, @production_db]

  if @connection.test( "ls -td #{previous_remote_dump_dirs_wildcard}" )
    dump_candidate = @connection.capture(:ls, '-td', previous_remote_dump_dirs_wildcard).split("\n")[0]

    dump_prompt(:use_remote_dump_dir, dump_candidate)

    if 'y' == fetch(:use_remote_dump_dir)
      dump_candidate
    else
      nil
    end
  else
    nil
  end
end

#last_remote_dump_tgzObject



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/capistrano/mongo_sync/mongo_sync.rb', line 95

def last_remote_dump_tgz
  previous_remote_dump_tgz_wildcard = '%s*.tgz' % File.join( @remote_dump_base, dump_dir_part )

  if @connection.test "ls -t #{previous_remote_dump_tgz_wildcard}"
    dump_candidate = @connection.capture(:ls, '-t', previous_remote_dump_tgz_wildcard).split("\n")[0]
    dump_prompt(:use_remote_dump_tgz, dump_candidate)

    if 'y' == fetch(:use_remote_dump_tgz)
      dump_candidate
    else
      nil
    end
  else
    nil
  end
end

#local_cleanup!Object



125
126
127
128
129
130
131
# File 'lib/capistrano/mongo_sync/mongo_sync.rb', line 125

def local_cleanup!
  pattern = File.join(@local_dump_base, '*')

  if @connection.test "find #{pattern} -mtime +1"
    @connection.execute :find, pattern, "-mtime +1 -exec rm {} \\;"
  end
end

#local_mongorestore!(local_dump_dir) ⇒ Object



162
163
164
165
166
167
168
169
170
# File 'lib/capistrano/mongo_sync/mongo_sync.rb', line 162

def local_mongorestore!(local_dump_dir)
  db_dump_path = File.join local_dump_dir, @from_db
  @connection.within( @local_dump_base ) do
    args = []
    args << '--drop' if drop_collection?
    args += ['-d', @development_db, db_dump_path]
    @connection.execute :mongorestore, *args
  end
end

#local_setup!Object

Local



121
122
123
# File 'lib/capistrano/mongo_sync/mongo_sync.rb', line 121

def local_setup!
  @connection.execute :mkdir, '-p', @local_dump_base
end

#local_unarchive!(local_tgz) ⇒ Object



151
152
153
154
155
156
157
158
159
160
# File 'lib/capistrano/mongo_sync/mongo_sync.rb', line 151

def local_unarchive!(local_tgz)
  local_dump_dir = File.join @local_dump_base, File.basename(local_tgz, '.tgz')
  if @connection.test("ls #{local_dump_dir}")
    # warn "Skipping untar and instead using previously unpacked dump_dir #{local_dump_dir}"
  else
    @connection.within( @local_dump_base ) do
      @connection.execute :tar, '-xzvf', local_tgz
    end
  end
end

#remote_archive!(dump_dir) ⇒ Object



112
113
114
115
116
117
118
# File 'lib/capistrano/mongo_sync/mongo_sync.rb', line 112

def remote_archive!( dump_dir )
  tar_filename = '%s.tgz' % dump_dir
  @connection.within( @remote_dump_base ) do
    @connection.execute :tar, '-czvf', tar_filename, dump_dir
  end
  File.join @remote_dump_base, tar_filename
end

#remote_cleanup!Object



40
41
42
43
44
45
46
# File 'lib/capistrano/mongo_sync/mongo_sync.rb', line 40

def remote_cleanup!
  pattern = File.join(@remote_dump_base, '*')

  if @connection.test "find #{pattern} -mtime +1"
    @connection.execute :find, pattern, "-mtime +1 -exec rm {} \\;"
  end
end

#remote_mongodump!Object



48
49
50
51
52
53
54
55
56
57
58
# File 'lib/capistrano/mongo_sync/mongo_sync.rb', line 48

def remote_mongodump!
  dump_dir = [dump_dir_part, Time.now.strftime('%Y-%m-%d-%H-%M')].join('-')

  args = ['-d', @from_db, '-o', File.join(@remote_dump_base, dump_dir)]
  args += ['-c', @collection] unless 'full' == @collection
  args += ['-q', collection_ids_arg] if @collection_ids

  @connection.execute :mongodump, *args

  dump_dir
end

#remote_setup!Object

Remote



36
37
38
# File 'lib/capistrano/mongo_sync/mongo_sync.rb', line 36

def remote_setup!
  @connection.execute :mkdir, '-p', @remote_dump_base
end

#staging_mongorestore!(remote_dump_dir) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/capistrano/mongo_sync/mongo_sync.rb', line 64

def staging_mongorestore!( remote_dump_dir )
  full_path_to_remote_dump_dir = if remote_dump_dir == File.basename(remote_dump_dir)
    File.join(@remote_dump_base, remote_dump_dir, @production_db)
  else
    remote_dump_dir
  end

  args = []
  args << '--drop' if drop_collection?
  args += ['-d', @staging_db, full_path_to_remote_dump_dir]
  @connection.execute :mongorestore, *args
end