shelly 0.2.24 → 0.2.25

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.2.25 / 2013-06-06
2
+
3
+ * [feature] It's possible to import PostgreSQL and MongoDB database from a dump file with `shelly backup import KIND FILENAME`. See our documentation for more info https://shellycloud.com/documentation/database_backups#import_database
4
+
1
5
  ## 0.2.24 / 2013-06-04
2
6
 
3
7
  * [bug] exit gracefully when downloaded or restored database backup doesn't exist
data/lib/shelly/app.rb CHANGED
@@ -120,6 +120,10 @@ module Shelly
120
120
  shelly.restore_backup(code_name, filename)
121
121
  end
122
122
 
123
+ def import_database(kind, filename)
124
+ ssh(:command => "import_database #{kind} #{filename}")
125
+ end
126
+
123
127
  def request_backup(kinds)
124
128
  Array(kinds).each do |kind|
125
129
  shelly.request_backup(code_name, kind)
@@ -342,7 +346,7 @@ module Shelly
342
346
 
343
347
  def ssh(options = {})
344
348
  conn = console_connection(options[:server])
345
- exec "ssh #{ssh_options(conn)} -t #{conn['host']} #{options[:command]}"
349
+ system "ssh #{ssh_options(conn)} -t #{conn['host']} #{options[:command]}"
346
350
  end
347
351
 
348
352
  def ssh_options(conn = console_connection)
@@ -350,7 +354,7 @@ module Shelly
350
354
  end
351
355
 
352
356
  def rsync(source, destination)
353
- exec "rsync -avz -e 'ssh #{ssh_options}' --progress #{source} #{destination}"
357
+ system "rsync -avz -e 'ssh #{ssh_options}' --progress #{source} #{destination}"
354
358
  end
355
359
  end
356
360
  end
@@ -9,7 +9,7 @@ module Shelly
9
9
  namespace :backup
10
10
  include Helpers
11
11
 
12
- before_hook :logged_in?, :only => [:list, :get, :create, :restore]
12
+ before_hook :logged_in?, :only => [:list, :get, :create, :restore, :import]
13
13
 
14
14
  class_option :cloud, :type => :string, :aliases => "-c", :desc => "Specify cloud"
15
15
 
@@ -85,7 +85,7 @@ module Shelly
85
85
  def restore(filename)
86
86
  app = multiple_clouds(options[:cloud], "backup restore FILENAME")
87
87
  backup = app.database_backup(filename)
88
- say "You are about restore database #{backup.kind} for cloud #{backup.code_name} to state from #{backup.filename}"
88
+ say "You are about restore #{backup.kind} database for cloud #{backup.code_name} to state from #{backup.filename}"
89
89
  say_new_line
90
90
  ask_to_restore_database
91
91
  app.restore_backup(filename)
@@ -98,6 +98,37 @@ module Shelly
98
98
  rescue Client::ConflictException => e
99
99
  say_error e[:message]
100
100
  end
101
+
102
+ desc "import KIND FILENAME", "Import database from dump file"
103
+ long_desc %{
104
+ Import database from local dump file to your cloud
105
+ KIND - Database kind. Possible values are: postgresql or mongodb
106
+ FILENAME - Database dump file or directory (mongodb), it has to be in current working directory.
107
+ }
108
+ def import(kind, filename)
109
+ app = multiple_clouds(options[:cloud], "backup import KIND FILENAME")
110
+ unless ::File.exist?(filename)
111
+ say_error "File #{filename} doesn't exist"
112
+ end
113
+ say "You are about import #{kind} database for cloud #{app} to state from file #{filename}"
114
+ ask_to_import_database
115
+ archive = compress(filename)
116
+ say "Uploading #{archive}", :green
117
+ app.upload(archive)
118
+ say "Uploading done", :green
119
+ say "Importing database", :green
120
+ app.import_database(kind, archive)
121
+ say "Database imported successfully", :green
122
+ end
123
+
124
+ no_tasks do
125
+ def compress(filename)
126
+ archive_name = "#{::File.basename(filename)}.tar"
127
+ say "Compressing #{filename} into #{archive_name}", :green
128
+ system("tar -cf #{archive_name} #{filename}")
129
+ archive_name
130
+ end
131
+ end
101
132
  end
102
133
  end
103
134
  end
@@ -72,6 +72,11 @@ More info at http://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository}
72
72
  say_new_line say_error "Canceled" unless delete_application == "yes"
73
73
  end
74
74
 
75
+ def ask_to_import_database
76
+ import_database = ask("I want to import the database (yes/no):")
77
+ say_new_line say_error "Canceled" unless import_database == "yes"
78
+ end
79
+
75
80
  def logged_in?
76
81
  user = Shelly::User.new
77
82
  user.token
@@ -1,3 +1,3 @@
1
1
  module Shelly
2
- VERSION = "0.2.24"
2
+ VERSION = "0.2.25"
3
3
  end
@@ -293,7 +293,7 @@ describe Shelly::App do
293
293
  it "should return result of rake task" do
294
294
  @client.stub(:console).and_return(
295
295
  {"host" => "console.example.com", "port" => "40010", "user" => "foo"})
296
- @app.should_receive(:exec).with("ssh -o StrictHostKeyChecking=no -p 40010 -l foo -t console.example.com rake_runner \"test\"")
296
+ @app.should_receive(:system).with("ssh -o StrictHostKeyChecking=no -p 40010 -l foo -t console.example.com rake_runner \"test\"")
297
297
  @app.rake("test")
298
298
  end
299
299
  end
@@ -302,7 +302,7 @@ describe Shelly::App do
302
302
  it "should return result of dbconsole" do
303
303
  @client.stub(:console).and_return(
304
304
  {"host" => "console.example.com", "port" => "40010", "user" => "foo"})
305
- @app.should_receive(:exec).with("ssh -o StrictHostKeyChecking=no -p 40010 -l foo -t console.example.com dbconsole")
305
+ @app.should_receive(:system).with("ssh -o StrictHostKeyChecking=no -p 40010 -l foo -t console.example.com dbconsole")
306
306
  @app.dbconsole
307
307
  end
308
308
  end
@@ -333,14 +333,14 @@ describe Shelly::App do
333
333
  it "should run ssh with all parameters" do
334
334
  @client.stub(:console).and_return(
335
335
  {"host" => "console.example.com", "port" => "40010", "user" => "foo"})
336
- @app.should_receive(:exec).with("ssh -o StrictHostKeyChecking=no -p 40010 -l foo -t console.example.com ")
336
+ @app.should_receive(:system).with("ssh -o StrictHostKeyChecking=no -p 40010 -l foo -t console.example.com ")
337
337
  @app.console
338
338
  end
339
339
 
340
340
  context "when server passed" do
341
341
  it "should request console on given server" do
342
342
  @client.should_receive(:console).with("foo-staging", "app1").and_return({})
343
- @app.stub(:exec)
343
+ @app.stub(:system)
344
344
  @app.console("app1")
345
345
  end
346
346
  end
@@ -357,7 +357,7 @@ describe Shelly::App do
357
357
  it "should run rsync with proper parameters" do
358
358
  @client.stub(:console).and_return(
359
359
  {"host" => "console.example.com", "port" => "40010", "user" => "foo"})
360
- @app.should_receive(:exec).with("rsync -avz -e 'ssh -o StrictHostKeyChecking=no -p 40010 -l foo' --progress /path console.example.com:/srv/glusterfs/disk")
360
+ @app.should_receive(:system).with("rsync -avz -e 'ssh -o StrictHostKeyChecking=no -p 40010 -l foo' --progress /path console.example.com:/srv/glusterfs/disk")
361
361
  @app.upload("/path")
362
362
  end
363
363
  end
@@ -366,7 +366,7 @@ describe Shelly::App do
366
366
  it "should run rsync with proper parameters" do
367
367
  @client.stub(:console).and_return(
368
368
  {"host" => "console.example.com", "port" => "40010", "user" => "foo"})
369
- @app.should_receive(:exec).with("rsync -avz -e 'ssh -o StrictHostKeyChecking=no -p 40010 -l foo' --progress console.example.com:/srv/glusterfs/disk/. /tmp")
369
+ @app.should_receive(:system).with("rsync -avz -e 'ssh -o StrictHostKeyChecking=no -p 40010 -l foo' --progress console.example.com:/srv/glusterfs/disk/. /tmp")
370
370
  @app.download(".", "/tmp")
371
371
  end
372
372
  end
@@ -193,8 +193,8 @@ describe Shelly::CLI::Backup do
193
193
 
194
194
  describe "restore" do
195
195
  before do
196
- @client.stub(:database_backup).and_return({"filename" => "better.tar.gz", "size" => 12345, "kind" => "postgre"})
197
- @client.stub(:restore_backup).and_return({"filename" => "better.tar.gz", "size" => 12345, "kind" => "postgre"})
196
+ @client.stub(:database_backup).and_return({"filename" => "better.tar.gz", "size" => 12345, "kind" => "postgresql"})
197
+ @client.stub(:restore_backup).and_return({"filename" => "better.tar.gz", "size" => 12345, "kind" => "postgresql"})
198
198
  $stdout.stub(:puts)
199
199
  $stdout.stub(:print)
200
200
  end
@@ -213,7 +213,7 @@ describe Shelly::CLI::Backup do
213
213
  end
214
214
 
215
215
  it "should restore database" do
216
- $stdout.should_receive(:puts).with("You are about restore database postgre for cloud foo-staging to state from better.tar.gz")
216
+ $stdout.should_receive(:puts).with("You are about restore postgresql database for cloud foo-staging to state from better.tar.gz")
217
217
  $stdout.should_receive(:print).with("I want to restore the database (yes/no): ")
218
218
  $stdout.should_receive(:puts).with("\n")
219
219
  @client.stub(:restore_backup).with("todo-list-test","better.tar.gz")
@@ -227,7 +227,7 @@ describe Shelly::CLI::Backup do
227
227
 
228
228
  context "when answering no" do
229
229
  it "should cancel restore database" do
230
- $stdout.should_receive(:puts).with("You are about restore database postgre for cloud foo-staging to state from better.tar.gz")
230
+ $stdout.should_receive(:puts).with("You are about restore postgresql database for cloud foo-staging to state from better.tar.gz")
231
231
  $stdout.should_receive(:print).with("I want to restore the database (yes/no): ")
232
232
  $stdout.should_receive(:puts).with("\n")
233
233
  $stdout.should_receive(:puts).with(red "Canceled")
@@ -251,4 +251,67 @@ describe Shelly::CLI::Backup do
251
251
  end
252
252
  end
253
253
  end
254
+
255
+ describe "#import" do
256
+ before do
257
+ FileUtils.touch("dump.sql")
258
+ @app.stub(:upload => nil, :ssh => nil)
259
+ @backup.stub(:system)
260
+ $stdout.stub(:puts)
261
+ $stdout.stub(:print)
262
+ end
263
+
264
+ it "should ensure user has logged in" do
265
+ hooks(@backup, :import).should include(:logged_in?)
266
+ end
267
+
268
+ it "should compress file" do
269
+ @backup.should_receive(:system).with("tar -cf dump.sql.tar dump.sql")
270
+ $stdout.should_receive(:puts).with(green "Compressing dump.sql into dump.sql.tar")
271
+ fake_stdin(["yes"]) do
272
+ invoke(@backup, :import, "postgresql", "dump.sql")
273
+ end
274
+ end
275
+
276
+ it "should upload compressed file" do
277
+ @app.should_receive(:upload).with("dump.sql.tar")
278
+ $stdout.should_receive(:puts).with(green "Uploading dump.sql.tar")
279
+ fake_stdin(["yes"]) do
280
+ invoke(@backup, :import, "postgresql", "dump.sql")
281
+ end
282
+ end
283
+
284
+ it "should import given database from uploaded file" do
285
+ @app.should_receive(:ssh).with(:command => "import_database postgresql dump.sql.tar")
286
+ $stdout.should_receive(:puts).with(green "Importing database")
287
+ fake_stdin(["yes"]) do
288
+ invoke(@backup, :import, "postgresql", "dump.sql")
289
+ end
290
+ end
291
+
292
+ context "on answering no" do
293
+ it "should cancel database import" do
294
+ $stdout.should_receive(:puts).with("You are about import postgresql database for cloud foo-staging to state from file dump.sql")
295
+ $stdout.should_receive(:print).with("I want to import the database (yes/no): ")
296
+ $stdout.should_receive(:puts).with(red "Canceled")
297
+ lambda {
298
+ fake_stdin(["no"]) do
299
+ invoke(@backup, :import, "postgresql", "dump.sql")
300
+ end
301
+ }.should raise_error(SystemExit)
302
+ end
303
+ end
304
+
305
+ context "file doesn't exist" do
306
+ it "should exit with error" do
307
+ FileUtils.rm("dump.sql")
308
+ $stdout.should_receive(:puts).with(red "File dump.sql doesn't exist")
309
+ lambda {
310
+ fake_stdin(["yes"]) do
311
+ invoke(@backup, :import, "postgresql", "dump.sql")
312
+ end
313
+ }.should raise_error(SystemExit)
314
+ end
315
+ end
316
+ end
254
317
  end
metadata CHANGED
@@ -1,207 +1,236 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shelly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.24
4
+ prerelease:
5
+ version: 0.2.25
5
6
  platform: ruby
6
7
  authors:
7
8
  - Shelly Cloud team
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2013-06-04 00:00:00.000000000 Z
12
+ date: 2013-06-06 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: rspec
16
+ type: :development
15
17
  requirement: !ruby/object:Gem::Requirement
18
+ none: false
16
19
  requirements:
17
20
  - - ~>
18
21
  - !ruby/object:Gem::Version
19
22
  version: 2.11.0
20
- type: :development
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
23
26
  requirements:
24
27
  - - ~>
25
28
  - !ruby/object:Gem::Version
26
29
  version: 2.11.0
27
30
  - !ruby/object:Gem::Dependency
28
31
  name: rake
32
+ type: :development
29
33
  requirement: !ruby/object:Gem::Requirement
34
+ none: false
30
35
  requirements:
31
36
  - - ! '>='
32
37
  - !ruby/object:Gem::Version
33
38
  version: '0'
34
- type: :development
35
39
  prerelease: false
36
40
  version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
37
42
  requirements:
38
43
  - - ! '>='
39
44
  - !ruby/object:Gem::Version
40
45
  version: '0'
41
46
  - !ruby/object:Gem::Dependency
42
47
  name: guard
48
+ type: :development
43
49
  requirement: !ruby/object:Gem::Requirement
50
+ none: false
44
51
  requirements:
45
52
  - - ! '>='
46
53
  - !ruby/object:Gem::Version
47
54
  version: '0'
48
- type: :development
49
55
  prerelease: false
50
56
  version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
51
58
  requirements:
52
59
  - - ! '>='
53
60
  - !ruby/object:Gem::Version
54
61
  version: '0'
55
62
  - !ruby/object:Gem::Dependency
56
63
  name: guard-rspec
64
+ type: :development
57
65
  requirement: !ruby/object:Gem::Requirement
66
+ none: false
58
67
  requirements:
59
68
  - - ! '>='
60
69
  - !ruby/object:Gem::Version
61
70
  version: '0'
62
- type: :development
63
71
  prerelease: false
64
72
  version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
65
74
  requirements:
66
75
  - - ! '>='
67
76
  - !ruby/object:Gem::Version
68
77
  version: '0'
69
78
  - !ruby/object:Gem::Dependency
70
79
  name: simplecov
80
+ type: :development
71
81
  requirement: !ruby/object:Gem::Requirement
82
+ none: false
72
83
  requirements:
73
84
  - - ! '>='
74
85
  - !ruby/object:Gem::Version
75
86
  version: '0'
76
- type: :development
77
87
  prerelease: false
78
88
  version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
79
90
  requirements:
80
91
  - - ! '>='
81
92
  - !ruby/object:Gem::Version
82
93
  version: '0'
83
94
  - !ruby/object:Gem::Dependency
84
95
  name: ruby_gntp
96
+ type: :development
85
97
  requirement: !ruby/object:Gem::Requirement
98
+ none: false
86
99
  requirements:
87
100
  - - ! '>='
88
101
  - !ruby/object:Gem::Version
89
102
  version: '0'
90
- type: :development
91
103
  prerelease: false
92
104
  version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
93
106
  requirements:
94
107
  - - ! '>='
95
108
  - !ruby/object:Gem::Version
96
109
  version: '0'
97
110
  - !ruby/object:Gem::Dependency
98
111
  name: rb-fsevent
112
+ type: :development
99
113
  requirement: !ruby/object:Gem::Requirement
114
+ none: false
100
115
  requirements:
101
116
  - - ! '>='
102
117
  - !ruby/object:Gem::Version
103
118
  version: '0'
104
- type: :development
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
107
122
  requirements:
108
123
  - - ! '>='
109
124
  - !ruby/object:Gem::Version
110
125
  version: '0'
111
126
  - !ruby/object:Gem::Dependency
112
127
  name: fakefs
128
+ type: :development
113
129
  requirement: !ruby/object:Gem::Requirement
130
+ none: false
114
131
  requirements:
115
132
  - - ! '>='
116
133
  - !ruby/object:Gem::Version
117
134
  version: '0'
118
- type: :development
119
135
  prerelease: false
120
136
  version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
121
138
  requirements:
122
139
  - - ! '>='
123
140
  - !ruby/object:Gem::Version
124
141
  version: '0'
125
142
  - !ruby/object:Gem::Dependency
126
143
  name: fakeweb
144
+ type: :development
127
145
  requirement: !ruby/object:Gem::Requirement
146
+ none: false
128
147
  requirements:
129
148
  - - ! '>='
130
149
  - !ruby/object:Gem::Version
131
150
  version: '0'
132
- type: :development
133
151
  prerelease: false
134
152
  version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
135
154
  requirements:
136
155
  - - ! '>='
137
156
  - !ruby/object:Gem::Version
138
157
  version: '0'
139
158
  - !ruby/object:Gem::Dependency
140
159
  name: wijet-thor
160
+ type: :runtime
141
161
  requirement: !ruby/object:Gem::Requirement
162
+ none: false
142
163
  requirements:
143
164
  - - ~>
144
165
  - !ruby/object:Gem::Version
145
166
  version: 0.14.9
146
- type: :runtime
147
167
  prerelease: false
148
168
  version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
149
170
  requirements:
150
171
  - - ~>
151
172
  - !ruby/object:Gem::Version
152
173
  version: 0.14.9
153
174
  - !ruby/object:Gem::Dependency
154
175
  name: rest-client
176
+ type: :runtime
155
177
  requirement: !ruby/object:Gem::Requirement
178
+ none: false
156
179
  requirements:
157
180
  - - ! '>='
158
181
  - !ruby/object:Gem::Version
159
182
  version: '0'
160
- type: :runtime
161
183
  prerelease: false
162
184
  version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
163
186
  requirements:
164
187
  - - ! '>='
165
188
  - !ruby/object:Gem::Version
166
189
  version: '0'
167
190
  - !ruby/object:Gem::Dependency
168
191
  name: json
192
+ type: :runtime
169
193
  requirement: !ruby/object:Gem::Requirement
194
+ none: false
170
195
  requirements:
171
196
  - - ! '>='
172
197
  - !ruby/object:Gem::Version
173
198
  version: '0'
174
- type: :runtime
175
199
  prerelease: false
176
200
  version_requirements: !ruby/object:Gem::Requirement
201
+ none: false
177
202
  requirements:
178
203
  - - ! '>='
179
204
  - !ruby/object:Gem::Version
180
205
  version: '0'
181
206
  - !ruby/object:Gem::Dependency
182
207
  name: progressbar
208
+ type: :runtime
183
209
  requirement: !ruby/object:Gem::Requirement
210
+ none: false
184
211
  requirements:
185
212
  - - ! '>='
186
213
  - !ruby/object:Gem::Version
187
214
  version: '0'
188
- type: :runtime
189
215
  prerelease: false
190
216
  version_requirements: !ruby/object:Gem::Requirement
217
+ none: false
191
218
  requirements:
192
219
  - - ! '>='
193
220
  - !ruby/object:Gem::Version
194
221
  version: '0'
195
222
  - !ruby/object:Gem::Dependency
196
223
  name: launchy
224
+ type: :runtime
197
225
  requirement: !ruby/object:Gem::Requirement
226
+ none: false
198
227
  requirements:
199
228
  - - ! '>='
200
229
  - !ruby/object:Gem::Version
201
230
  version: '0'
202
- type: :runtime
203
231
  prerelease: false
204
232
  version_requirements: !ruby/object:Gem::Requirement
233
+ none: false
205
234
  requirements:
206
235
  - - ! '>='
207
236
  - !ruby/object:Gem::Version
@@ -276,26 +305,27 @@ files:
276
305
  - spec/thor/options_spec.rb
277
306
  homepage: http://shellycloud.com
278
307
  licenses: []
279
- metadata: {}
280
308
  post_install_message:
281
309
  rdoc_options: []
282
310
  require_paths:
283
311
  - lib
284
312
  required_ruby_version: !ruby/object:Gem::Requirement
313
+ none: false
285
314
  requirements:
286
315
  - - ! '>='
287
316
  - !ruby/object:Gem::Version
288
317
  version: '0'
289
318
  required_rubygems_version: !ruby/object:Gem::Requirement
319
+ none: false
290
320
  requirements:
291
321
  - - ! '>='
292
322
  - !ruby/object:Gem::Version
293
323
  version: '0'
294
324
  requirements: []
295
325
  rubyforge_project: shelly
296
- rubygems_version: 2.0.3
326
+ rubygems_version: 1.8.23
297
327
  signing_key:
298
- specification_version: 4
328
+ specification_version: 3
299
329
  summary: Shelly Cloud command line tool
300
330
  test_files:
301
331
  - spec/helpers.rb
checksums.yaml DELETED
@@ -1,15 +0,0 @@
1
- ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MWM5MmE2NjRhNGJmMjM1YzBjYzEzNWQwMzMxODlmZjlkZWZmZDU1YQ==
5
- data.tar.gz: !binary |-
6
- MTQwNDM4OTY5NGU4NDI2MWY1MmUyN2JmZTNmOGZkZTFkZDc4OTljMA==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- NTJhMTU1ZWQ5ZjgyNGEzNWRkYjBhZjAyYzUwN2VmMThiN2NlNDVmYmI3YTdk
10
- MjQ1ZjI0OTA3Zjk3MjE5NjJiNmZkMmUyODdmOTU5ODBiNWJhMTQ3MTgxZTVm
11
- ZDMzMWI0Zjk2NjQzNjY1YjQxZmU0YWZhMzcyNTdlMmQ3ZWFlYjg=
12
- data.tar.gz: !binary |-
13
- NzNhZTEzMjljOWYyNmEyOTQ2MDE0ZDYyZjkxZGIyMzkyYjJhMDE2ZGZkNGZk
14
- NmUwZjE3Y2VlNTI2MWU2MGY4NTlkYzgzOTU3ODA1ZmFhMDIyZDA4OTdhYzFh
15
- NjMyNzhlOTBmMjYzN2ZmNjRkZGU4OTcyNmM4Y2U4NTFjMzQzN2Y=