shelly 0.0.41.pre → 0.0.41

Sign up to get free protection for your applications and to get access to all the features.
data/lib/shelly/app.rb CHANGED
@@ -74,6 +74,10 @@ module Shelly
74
74
  Shelly::Backup.new(attributes.merge("code_name" => code_name))
75
75
  end
76
76
 
77
+ def restore_backup(filename)
78
+ shelly.restore_backup(code_name, filename)
79
+ end
80
+
77
81
  def request_backup(kind)
78
82
  shelly.request_backup(code_name, kind)
79
83
  end
data/lib/shelly/backup.rb CHANGED
@@ -1,12 +1,13 @@
1
1
  module Shelly
2
2
  class Backup < Model
3
- attr_reader :filename, :size, :human_size, :code_name
3
+ attr_reader :filename, :size, :human_size, :code_name, :kind
4
4
 
5
5
  def initialize(attributes = {})
6
6
  @filename = attributes["filename"]
7
7
  @size = attributes["size"]
8
8
  @human_size = attributes["human_size"]
9
9
  @code_name = attributes["code_name"]
10
+ @kind = attributes["kind"]
10
11
  end
11
12
 
12
13
  def download(callback)
@@ -65,7 +65,7 @@ module Shelly
65
65
  def create(kind = nil)
66
66
  multiple_clouds(options[:cloud], "backup create", "Select cloud to create snapshot of database")
67
67
  @app.request_backup(kind)
68
- say "Backup requested. It can take up to several minutes for" +
68
+ say "Backup requested. It can take up to several minutes for " +
69
69
  "the backup process to finish and the backup to show up in backups list.", :green
70
70
  rescue Client::APIError => e
71
71
  if e.not_found?
@@ -74,6 +74,29 @@ module Shelly
74
74
  say_error e.message
75
75
  end
76
76
  end
77
+
78
+ desc "restore <filename>", "Restore database to state from filename"
79
+ method_option :cloud, :type => :string, :aliases => "-c",
80
+ :desc => "Specify which cloud to restore database snapshot for"
81
+ def restore(filename = nil)
82
+ logged_in?
83
+ multiple_clouds(options[:cloud], "backup restore <filename>", "Select cloud for which you want restore backup")
84
+ say_error "Filename is required" unless filename
85
+ backup = @app.database_backup(filename)
86
+ say "You are about restore database #{backup.kind} for cloud #{backup.code_name} to state from #{backup.filename}"
87
+ say_new_line
88
+ ask_to_restore_database
89
+ @app.restore_backup(filename)
90
+ say_new_line
91
+ say "Restore has been scheduled. Wait few minutes till database is restored."
92
+ rescue Client::APIError => e
93
+ if e.not_found?
94
+ say_error "Backup not found", :with_exit => false
95
+ say "You can list available backups with 'shelly backup list' command"
96
+ else
97
+ raise e
98
+ end
99
+ end
77
100
  end
78
101
  end
79
102
  end
@@ -60,13 +60,8 @@ module Shelly
60
60
  user.password = ask_for_password(:with_confirmation => false)
61
61
  user.login
62
62
  say "Login successful"
63
- # FIXME: remove conflict boolean, move it to rescue block
64
- begin user.upload_ssh_key
65
- conflict = false
66
- rescue RestClient::Conflict
67
- conflict = true
68
- end
69
- say "Uploading your public SSH key" if conflict == false
63
+ user.upload_ssh_key
64
+ say "Uploading your public SSH key"
70
65
  list
71
66
  rescue Client::APIError => e
72
67
  if e.validation?
data/lib/shelly/client.rb CHANGED
@@ -6,7 +6,7 @@ module Shelly
6
6
  class Client
7
7
  class APIError < Exception
8
8
  attr_reader :status_code, :body
9
-
9
+
10
10
  def initialize(status_code, body = {})
11
11
  @status_code = status_code
12
12
  @body = body
@@ -118,7 +118,7 @@ module Shelly
118
118
  def apps
119
119
  get("/apps")
120
120
  end
121
-
121
+
122
122
  def app(code_name)
123
123
  get("/apps/#{code_name}")
124
124
  end
@@ -138,11 +138,15 @@ module Shelly
138
138
  def database_backups(code_name)
139
139
  get("/apps/#{code_name}/database_backups")
140
140
  end
141
-
141
+
142
142
  def database_backup(code_name, handler)
143
143
  get("/apps/#{code_name}/database_backups/#{handler}")
144
144
  end
145
145
 
146
+ def restore_backup(code_name, filename)
147
+ put("/apps/#{code_name}/database_backups/#{filename}/restore")
148
+ end
149
+
146
150
  def request_backup(code_name, kind = nil)
147
151
  post("/apps/#{code_name}/database_backups", :kind => kind)
148
152
  end
@@ -170,7 +174,7 @@ module Shelly
170
174
  def delete(path, params = {})
171
175
  request(path, :delete, params)
172
176
  end
173
-
177
+
174
178
  def download_backup(cloud, filename, progress_callback = nil)
175
179
  File.open(filename, "w") do |out|
176
180
  process_response = lambda do |response|
@@ -181,9 +185,9 @@ module Shelly
181
185
  end
182
186
 
183
187
  options = request_parameters("/apps/#{cloud}/database_backups/#{filename}", :get)
184
- options = options.merge(:block_response => process_response,
188
+ options = options.merge(:block_response => process_response,
185
189
  :headers => {:accept => "application/x-gzip"})
186
-
190
+
187
191
  RestClient::Request.execute(options)
188
192
  end
189
193
  end
@@ -53,6 +53,12 @@ module Shelly
53
53
  say_error "No Cloudfile found" unless Cloudfile.present?
54
54
  end
55
55
 
56
+ def ask_to_restore_database
57
+ delete_application_question = "I want to restore the database (yes/no):"
58
+ delete_application = ask(delete_application_question)
59
+ say_new_line say_error "Canceled" unless delete_application == "yes"
60
+ end
61
+
56
62
  def logged_in?
57
63
  user = Shelly::User.new
58
64
  user.token
@@ -1,3 +1,3 @@
1
1
  module Shelly
2
- VERSION = "0.0.41.pre"
2
+ VERSION = "0.0.41"
3
3
  end
@@ -149,9 +149,63 @@ describe Shelly::CLI::Backup do
149
149
 
150
150
  it "should display information about request backup" do
151
151
  @client.stub(:request_backup)
152
- $stdout.should_receive(:puts).with(green "Backup requested. It can take up to several minutes for" +
152
+ $stdout.should_receive(:puts).with(green "Backup requested. It can take up to several minutes for " +
153
153
  "the backup process to finish and the backup to show up in backups list.")
154
154
  invoke(@backup, :create)
155
155
  end
156
156
  end
157
+
158
+ describe "restore" do
159
+ before do
160
+ @client.stub(:database_backup).and_return({"filename" => "better.tar.gz", "size" => 12345, "kind" => "postgre"})
161
+ @client.stub(:restore_backup).and_return({"filename" => "better.tar.gz", "size" => 12345, "kind" => "postgre"})
162
+ $stdout.stub(:puts)
163
+ end
164
+
165
+ it "should restore database" do
166
+ $stdout.should_receive(:puts).with("You are about restore database postgre for cloud foo-staging to state from better.tar.gz")
167
+ $stdout.should_receive(:print).with("I want to restore the database (yes/no): ")
168
+ $stdout.should_receive(:puts).with("\n")
169
+ @client.stub(:restore_backup).with("todo-list-test","better.tar.gz")
170
+ $stdout.should_receive(:puts).with("\n")
171
+ $stdout.should_receive(:puts).with("Restore has been scheduled. Wait few minutes till database is restored.")
172
+
173
+ fake_stdin(["yes"]) do
174
+ @backup.restore("better.tar.gz")
175
+ end
176
+ end
177
+
178
+ context "on type no" do
179
+ it "should cancel restore database" do
180
+ $stdout.should_receive(:puts).with("You are about restore database postgre for cloud foo-staging to state from better.tar.gz")
181
+ $stdout.should_receive(:print).with("I want to restore the database (yes/no): ")
182
+ $stdout.should_receive(:puts).with("\n")
183
+ $stdout.should_receive(:puts).with(red "Canceled")
184
+
185
+ lambda {
186
+ fake_stdin(["no"]) do
187
+ @backup.restore("better.tar.gz")
188
+ end
189
+ }.should raise_error(SystemExit)
190
+ end
191
+ end
192
+
193
+ it "should exit with 1 when filename is not specified" do
194
+ $stdout.should_receive(:puts).with(red "Filename is required")
195
+ lambda {
196
+ @backup.restore
197
+ }.should raise_error(SystemExit)
198
+ end
199
+
200
+ context "on backup not found" do
201
+ it "should display error message" do
202
+ response = {"message" => "Backup restore not found"}
203
+ exception = Shelly::Client::APIError.new(404, response)
204
+ @client.stub(:database_backup).and_raise(exception)
205
+ $stdout.should_receive(:puts).with(red "Backup not found")
206
+ $stdout.should_receive(:puts).with("You can list available backups with 'shelly backup list' command")
207
+ @backup.restore("better.tar.gz")
208
+ end
209
+ end
210
+ end
157
211
  end
@@ -227,14 +227,6 @@ OUT
227
227
  end
228
228
  end
229
229
 
230
- it "should upload user's public SSH key and raise HTTP status 409 Conflict when SSH key exists in database" do
231
- @user.should_receive(:upload_ssh_key).and_raise(RestClient::Conflict)
232
- $stdout.should_receive(:puts).with("\e[32mYou have following clouds available:\e[0m")
233
- fake_stdin(["megan@example.com", "secret"]) do
234
- invoke(@main, :login)
235
- end
236
- end
237
-
238
230
  it "should display list of applications to which user has access" do
239
231
  $stdout.should_receive(:puts).with("\e[32mYou have following clouds available:\e[0m")
240
232
  $stdout.should_receive(:puts).with(/ abc\s+\| running/)
metadata CHANGED
@@ -1,167 +1,188 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: shelly
3
- version: !ruby/object:Gem::Version
4
- version: 0.0.41.pre
5
- prerelease: 7
3
+ version: !ruby/object:Gem::Version
4
+ hash: 77
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 41
10
+ version: 0.0.41
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Shelly Cloud team
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2012-01-02 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2012-01-02 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
15
21
  name: rspec
16
- requirement: &70129852876100 !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
22
- type: :development
23
22
  prerelease: false
24
- version_requirements: *70129852876100
25
- - !ruby/object:Gem::Dependency
26
- name: rake
27
- requirement: &70129852875680 !ruby/object:Gem::Requirement
23
+ requirement: &id001 !ruby/object:Gem::Requirement
28
24
  none: false
29
- requirements:
30
- - - ! '>='
31
- - !ruby/object:Gem::Version
32
- version: '0'
33
- type: :development
34
- prerelease: false
35
- version_requirements: *70129852875680
36
- - !ruby/object:Gem::Dependency
37
- name: guard
38
- requirement: &70129852875260 !ruby/object:Gem::Requirement
39
- none: false
40
- requirements:
41
- - - ! '>='
42
- - !ruby/object:Gem::Version
43
- version: '0'
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
44
32
  type: :development
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: rake
45
36
  prerelease: false
46
- version_requirements: *70129852875260
47
- - !ruby/object:Gem::Dependency
48
- name: guard-rspec
49
- requirement: &70129852874840 !ruby/object:Gem::Requirement
37
+ requirement: &id002 !ruby/object:Gem::Requirement
50
38
  none: false
51
- requirements:
52
- - - ! '>='
53
- - !ruby/object:Gem::Version
54
- version: '0'
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ hash: 3
43
+ segments:
44
+ - 0
45
+ version: "0"
55
46
  type: :development
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: guard
56
50
  prerelease: false
57
- version_requirements: *70129852874840
58
- - !ruby/object:Gem::Dependency
59
- name: growl_notify
60
- requirement: &70129852890740 !ruby/object:Gem::Requirement
51
+ requirement: &id003 !ruby/object:Gem::Requirement
61
52
  none: false
62
- requirements:
63
- - - ! '>='
64
- - !ruby/object:Gem::Version
65
- version: '0'
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
66
60
  type: :development
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: guard-rspec
67
64
  prerelease: false
68
- version_requirements: *70129852890740
69
- - !ruby/object:Gem::Dependency
70
- name: rb-fsevent
71
- requirement: &70129852890320 !ruby/object:Gem::Requirement
65
+ requirement: &id004 !ruby/object:Gem::Requirement
72
66
  none: false
73
- requirements:
74
- - - ! '>='
75
- - !ruby/object:Gem::Version
76
- version: '0'
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
77
74
  type: :development
78
- prerelease: false
79
- version_requirements: *70129852890320
80
- - !ruby/object:Gem::Dependency
75
+ version_requirements: *id004
76
+ - !ruby/object:Gem::Dependency
81
77
  name: fakefs
82
- requirement: &70129852889900 !ruby/object:Gem::Requirement
78
+ prerelease: false
79
+ requirement: &id005 !ruby/object:Gem::Requirement
83
80
  none: false
84
- requirements:
85
- - - ! '>='
86
- - !ruby/object:Gem::Version
87
- version: '0'
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ hash: 3
85
+ segments:
86
+ - 0
87
+ version: "0"
88
88
  type: :development
89
- prerelease: false
90
- version_requirements: *70129852889900
91
- - !ruby/object:Gem::Dependency
89
+ version_requirements: *id005
90
+ - !ruby/object:Gem::Dependency
92
91
  name: fakeweb
93
- requirement: &70129852889480 !ruby/object:Gem::Requirement
92
+ prerelease: false
93
+ requirement: &id006 !ruby/object:Gem::Requirement
94
94
  none: false
95
- requirements:
96
- - - ! '>='
97
- - !ruby/object:Gem::Version
98
- version: '0'
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ hash: 3
99
+ segments:
100
+ - 0
101
+ version: "0"
99
102
  type: :development
100
- prerelease: false
101
- version_requirements: *70129852889480
102
- - !ruby/object:Gem::Dependency
103
+ version_requirements: *id006
104
+ - !ruby/object:Gem::Dependency
103
105
  name: wijet-thor
104
- requirement: &70129852888980 !ruby/object:Gem::Requirement
106
+ prerelease: false
107
+ requirement: &id007 !ruby/object:Gem::Requirement
105
108
  none: false
106
- requirements:
109
+ requirements:
107
110
  - - ~>
108
- - !ruby/object:Gem::Version
111
+ - !ruby/object:Gem::Version
112
+ hash: 41
113
+ segments:
114
+ - 0
115
+ - 14
116
+ - 7
109
117
  version: 0.14.7
110
118
  type: :runtime
111
- prerelease: false
112
- version_requirements: *70129852888980
113
- - !ruby/object:Gem::Dependency
119
+ version_requirements: *id007
120
+ - !ruby/object:Gem::Dependency
114
121
  name: rest-client
115
- requirement: &70129852888560 !ruby/object:Gem::Requirement
122
+ prerelease: false
123
+ requirement: &id008 !ruby/object:Gem::Requirement
116
124
  none: false
117
- requirements:
118
- - - ! '>='
119
- - !ruby/object:Gem::Version
120
- version: '0'
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ hash: 3
129
+ segments:
130
+ - 0
131
+ version: "0"
121
132
  type: :runtime
122
- prerelease: false
123
- version_requirements: *70129852888560
124
- - !ruby/object:Gem::Dependency
133
+ version_requirements: *id008
134
+ - !ruby/object:Gem::Dependency
125
135
  name: json
126
- requirement: &70129852888100 !ruby/object:Gem::Requirement
136
+ prerelease: false
137
+ requirement: &id009 !ruby/object:Gem::Requirement
127
138
  none: false
128
- requirements:
129
- - - ! '>='
130
- - !ruby/object:Gem::Version
131
- version: '0'
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ hash: 3
143
+ segments:
144
+ - 0
145
+ version: "0"
132
146
  type: :runtime
133
- prerelease: false
134
- version_requirements: *70129852888100
135
- - !ruby/object:Gem::Dependency
147
+ version_requirements: *id009
148
+ - !ruby/object:Gem::Dependency
136
149
  name: wijet-launchy
137
- requirement: &70129852887680 !ruby/object:Gem::Requirement
150
+ prerelease: false
151
+ requirement: &id010 !ruby/object:Gem::Requirement
138
152
  none: false
139
- requirements:
140
- - - ! '>='
141
- - !ruby/object:Gem::Version
142
- version: '0'
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ hash: 3
157
+ segments:
158
+ - 0
159
+ version: "0"
143
160
  type: :runtime
144
- prerelease: false
145
- version_requirements: *70129852887680
146
- - !ruby/object:Gem::Dependency
161
+ version_requirements: *id010
162
+ - !ruby/object:Gem::Dependency
147
163
  name: progressbar
148
- requirement: &70129852887260 !ruby/object:Gem::Requirement
164
+ prerelease: false
165
+ requirement: &id011 !ruby/object:Gem::Requirement
149
166
  none: false
150
- requirements:
151
- - - ! '>='
152
- - !ruby/object:Gem::Version
153
- version: '0'
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ hash: 3
171
+ segments:
172
+ - 0
173
+ version: "0"
154
174
  type: :runtime
155
- prerelease: false
156
- version_requirements: *70129852887260
175
+ version_requirements: *id011
157
176
  description: Tool for managing applications and clouds at shellycloud.com
158
- email:
177
+ email:
159
178
  - support@shellycloud.com
160
- executables:
179
+ executables:
161
180
  - shelly
162
181
  extensions: []
182
+
163
183
  extra_rdoc_files: []
164
- files:
184
+
185
+ files:
165
186
  - .gitignore
166
187
  - .travis.yml
167
188
  - Gemfile
@@ -213,43 +234,36 @@ files:
213
234
  - spec/thor/options_spec.rb
214
235
  homepage: http://shellycloud.com
215
236
  licenses: []
237
+
216
238
  post_install_message:
217
239
  rdoc_options: []
218
- require_paths:
240
+
241
+ require_paths:
219
242
  - lib
220
- required_ruby_version: !ruby/object:Gem::Requirement
243
+ required_ruby_version: !ruby/object:Gem::Requirement
221
244
  none: false
222
- requirements:
223
- - - ! '>='
224
- - !ruby/object:Gem::Version
225
- version: '0'
226
- required_rubygems_version: !ruby/object:Gem::Requirement
245
+ requirements:
246
+ - - ">="
247
+ - !ruby/object:Gem::Version
248
+ hash: 3
249
+ segments:
250
+ - 0
251
+ version: "0"
252
+ required_rubygems_version: !ruby/object:Gem::Requirement
227
253
  none: false
228
- requirements:
229
- - - ! '>'
230
- - !ruby/object:Gem::Version
231
- version: 1.3.1
254
+ requirements:
255
+ - - ">="
256
+ - !ruby/object:Gem::Version
257
+ hash: 3
258
+ segments:
259
+ - 0
260
+ version: "0"
232
261
  requirements: []
262
+
233
263
  rubyforge_project: shelly
234
264
  rubygems_version: 1.8.10
235
265
  signing_key:
236
266
  specification_version: 3
237
267
  summary: Shelly Cloud command line tool
238
- test_files:
239
- - spec/helpers.rb
240
- - spec/input_faker.rb
241
- - spec/shelly/app_spec.rb
242
- - spec/shelly/backup_spec.rb
243
- - spec/shelly/cli/backup_spec.rb
244
- - spec/shelly/cli/config_spec.rb
245
- - spec/shelly/cli/deploys_spec.rb
246
- - spec/shelly/cli/main_spec.rb
247
- - spec/shelly/cli/runner_spec.rb
248
- - spec/shelly/cli/user_spec.rb
249
- - spec/shelly/client_spec.rb
250
- - spec/shelly/cloudfile_spec.rb
251
- - spec/shelly/download_progress_bar_spec.rb
252
- - spec/shelly/model_spec.rb
253
- - spec/shelly/user_spec.rb
254
- - spec/spec_helper.rb
255
- - spec/thor/options_spec.rb
268
+ test_files: []
269
+