shelly 0.0.43 → 0.0.44.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,23 +9,24 @@ module Shelly
9
9
  class Main < Command
10
10
  include Thor::Actions
11
11
 
12
- register(User, "user", "user <command>", "Manages users using this cloud")
13
- register(Backup, "backup", "backup <command>", "Manages database backups from this cloud")
14
- register(Deploys, "deploys", "deploys <command>", "View cloud deploy logs")
15
- register(Config, "config", "config <command>", "Manages cloud configuration files")
12
+ register(User, "user", "user <command>", "Manage collaborators")
13
+ register(Backup, "backup", "backup <command>", "Manage database backups")
14
+ register(Deploys, "deploys", "deploys <command>", "View deploy logs")
15
+ register(Config, "config", "config <command>", "Manage application configuration files")
16
16
  check_unknown_options!
17
17
 
18
- before_hook :logged_in?, :only => [:add, :list, :start, :stop, :logs, :delete]
19
- before_hook :inside_git_repository?, :only => [:add, :ip]
18
+ # FIXME: it should be possible to pass single symbol, instead of one element array
19
+ before_hook :logged_in?, :only => [:add, :list, :start, :stop, :logs, :delete, :ip, :logout]
20
+ before_hook :inside_git_repository?, :only => [:add]
20
21
  before_hook :cloudfile_present?, :only => [:logs, :stop, :start, :ip]
21
22
 
22
23
  map %w(-v --version) => :version
23
- desc "version", "Displays shelly version"
24
+ desc "version", "Display shelly version"
24
25
  def version
25
26
  say "shelly version #{Shelly::VERSION}"
26
27
  end
27
28
 
28
- desc "register [EMAIL]", "Registers new user account on Shelly Cloud"
29
+ desc "register [EMAIL]", "Register new account"
29
30
  def register(email = nil)
30
31
  user = Shelly::User.new
31
32
  user.ssh_key_registered?
@@ -38,12 +39,10 @@ module Shelly
38
39
  end
39
40
  say "Successfully registered!"
40
41
  say "Check you mailbox for email address confirmation"
41
- rescue Client::APIError => e
42
- if e.validation?
43
- e.each_error { |error| say_error "#{error}", :with_exit => false }
44
- exit 1
45
- end
46
- rescue RestClient::Conflict
42
+ rescue Client::ValidationException => e
43
+ e.each_error { |error| say_error "#{error}", :with_exit => false }
44
+ exit 1
45
+ rescue Client::ConflictException
47
46
  say_error "User with your ssh key already exists.", :with_exit => false
48
47
  say_error "You can login using: shelly login [EMAIL]", :with_exit => false
49
48
  exit 1
@@ -52,7 +51,7 @@ module Shelly
52
51
  say_error "Use ssh-keygen to generate ssh key pair"
53
52
  end
54
53
 
55
- desc "login [EMAIL]", "Logs user in to Shelly Cloud"
54
+ desc "login [EMAIL]", "Log into Shelly Cloud"
56
55
  def login(email = nil)
57
56
  user = Shelly::User.new
58
57
  raise Errno::ENOENT, user.ssh_key_path unless user.ssh_key_exists?
@@ -63,16 +62,12 @@ module Shelly
63
62
  user.upload_ssh_key
64
63
  say "Uploading your public SSH key"
65
64
  list
66
- rescue Client::APIError => e
67
- if e.validation?
68
- e.each_error { |error| say_error "#{error}", :with_exit => false }
69
- end
70
- if e.unauthorized?
71
- say_error "Wrong email or password", :with_exit => false
72
- say_error "You can reset password by using link:", :with_exit => false
73
- say_error "#{e.url}", :with_exit => false
74
- end
75
- exit 1
65
+ rescue Client::ValidationException => e
66
+ e.each_error { |error| say_error "#{error}", :with_exit => false }
67
+ rescue Client::UnauthorizedException => e
68
+ say_error "Wrong email or password", :with_exit => false
69
+ say_error "You can reset password by using link:", :with_exit => false
70
+ say_error "#{e[:url]}"
76
71
  rescue Errno::ENOENT => e
77
72
  say_error e, :with_exit => false
78
73
  say_error "Use ssh-keygen to generate ssh key pair"
@@ -82,11 +77,11 @@ module Shelly
82
77
  :desc => "Unique code-name of your cloud"
83
78
  method_option :databases, :type => :array, :aliases => "-d",
84
79
  :banner => Shelly::App::DATABASE_KINDS.join(', '),
85
- :desc => "Array of databases of your choice"
80
+ :desc => "List of databases of your choice"
86
81
  method_option :domains, :type => :array,
87
82
  :banner => "CODE-NAME.shellyapp.com, YOUR-DOMAIN.com",
88
- :desc => "Array of your domains"
89
- desc "add", "Adds new cloud to Shelly Cloud"
83
+ :desc => "List of your domains"
84
+ desc "add", "Add a new cloud"
90
85
  def add
91
86
  check_options(options)
92
87
  @app = Shelly::App.new
@@ -107,16 +102,14 @@ module Shelly
107
102
  info_adding_cloudfile_to_repository
108
103
  info_deploying_to_shellycloud
109
104
 
110
- rescue Client::APIError => e
111
- if e.validation?
112
- e.each_error { |error| say_error error, :with_exit => false }
113
- say_new_line
114
- say_error "Fix erros in the below command and type it again to create your cloud" , :with_exit => false
115
- say_error "shelly add --code-name=#{@app.code_name} --databases=#{@app.databases.join} --domains=#{@app.code_name}.shellyapp.com"
116
- end
105
+ rescue Client::ValidationException => e
106
+ e.each_error { |error| say_error error, :with_exit => false }
107
+ say_new_line
108
+ say_error "Fix erros in the below command and type it again to create your cloud" , :with_exit => false
109
+ say_error "shelly add --code-name=#{@app.code_name} --databases=#{@app.databases.join} --domains=#{@app.code_name}.shellyapp.com"
117
110
  end
118
111
 
119
- desc "list", "Lists all your clouds"
112
+ desc "list", "List available clouds"
120
113
  def list
121
114
  user = Shelly::User.new
122
115
  apps = user.apps
@@ -129,16 +122,12 @@ module Shelly
129
122
  else
130
123
  say "You have no clouds yet", :green
131
124
  end
132
- rescue Client::APIError => e
133
- if e.unauthorized?
134
- say_error "You are not logged in, use `shelly login`"
135
- end
136
125
  end
126
+
137
127
  map "status" => :list
138
128
 
139
- desc "ip", "Lists clouds IP's"
129
+ desc "ip", "List cloud's IP addresses"
140
130
  def ip
141
- say_error "No Cloudfile found" unless Cloudfile.present?
142
131
  @cloudfile = Cloudfile.new
143
132
  @cloudfile.clouds.each do |cloud|
144
133
  begin
@@ -146,31 +135,26 @@ module Shelly
146
135
  say "Cloud #{cloud}:", :green
147
136
  print_wrapped "Web server IP: #{@app.web_server_ip}", :ident => 2
148
137
  print_wrapped "Mail server IP: #{@app.mail_server_ip}", :ident => 2
149
- rescue Client::APIError => e
150
- if e.not_found?
151
- say_error "You have no access to '#{cloud}' cloud defined in Cloudfile", :with_exit => false
152
- else
153
- say_error e.message, :with_exit => false
154
- end
138
+ rescue Client::NotFoundException => e
139
+ raise unless e.resource == :cloud
140
+ say_error "You have no access to '#{cloud}' cloud defined in Cloudfile", :with_exit => false
155
141
  end
156
142
  end
157
143
  end
158
144
 
159
- desc "start", "Starts the cloud"
160
- method_option :cloud, :type => :string, :aliases => "-c",
161
- :desc => "Specify which cloud to start"
145
+ desc "start", "Start the cloud"
146
+ method_option :cloud, :type => :string, :aliases => "-c", :desc => "Specify cloud"
162
147
  def start
163
- multiple_clouds(options[:cloud], "start", "Select cloud to start using:")
148
+ multiple_clouds(options[:cloud], "start")
164
149
  @app.start
165
- say "Starting cloud #{@app.code_name}. Check status with:", :green
150
+ say "Starting cloud #{@app}. Check status with:", :green
166
151
  say " shelly list"
167
- rescue RestClient::Conflict => e
168
- response = JSON.parse(e.response)
169
- case response['state']
152
+ rescue Client::ConflictException => e
153
+ case e[:state]
170
154
  when "running"
171
- say_error "Not starting: cloud '#{@app.code_name}' is already running"
155
+ say_error "Not starting: cloud '#{@app}' is already running"
172
156
  when "deploying", "configuring"
173
- say_error "Not starting: cloud '#{@app.code_name}' is currently deploying"
157
+ say_error "Not starting: cloud '#{@app}' is currently deploying"
174
158
  when "no_code"
175
159
  say_error "Not starting: no source code provided", :with_exit => false
176
160
  say_error "Push source code using:", :with_exit => false
@@ -178,36 +162,32 @@ module Shelly
178
162
  when "deploy_failed", "configuration_failed"
179
163
  say_error "Not starting: deployment failed", :with_exit => false
180
164
  say_error "Support has been notified", :with_exit => false
181
- say_error "See #{response['link']} for reasons of failure"
165
+ say_error "Check `shelly deploys show last --cloud #{@app}` for reasons of failure"
182
166
  when "no_billing"
183
167
  say_error "Please fill in billing details to start foo-production. Opening browser.", :with_exit => false
184
168
  @app.open_billing_page
185
169
  end
186
170
  exit 1
187
- rescue Client::APIError => e
188
- if e.not_found?
189
- say_error "You have no access to '#{@app.code_name}' cloud defined in Cloudfile"
190
- end
171
+ rescue Client::NotFoundException => e
172
+ raise unless e.resource == :cloud
173
+ say_error "You have no access to '#{@app}' cloud defined in Cloudfile"
191
174
  end
192
175
 
193
- desc "stop", "Stops the cloud"
194
- method_option :cloud, :type => :string, :aliases => "-c",
195
- :desc => "Specify which cloud to stop"
176
+ desc "stop", "Stop the cloud"
177
+ method_option :cloud, :type => :string, :aliases => "-c", :desc => "Specify cloud"
196
178
  def stop
197
- multiple_clouds(options[:cloud], "stop", "Select cloud to stop using:")
179
+ multiple_clouds(options[:cloud], "stop")
198
180
  @app.stop
199
181
  say "Cloud '#{@app.code_name}' stopped"
200
- rescue Client::APIError => e
201
- if e.not_found?
202
- say_error "You have no access to '#{@app.code_name}' cloud defined in Cloudfile"
203
- end
182
+ rescue Client::NotFoundException => e
183
+ raise unless e.resource == :cloud
184
+ say_error "You have no access to '#{@app.code_name}' cloud defined in Cloudfile"
204
185
  end
205
186
 
206
- desc "delete", "Delete cloud from Shelly Cloud"
207
- method_option :cloud, :type => :string, :aliases => "-c",
208
- :desc => "Specify which cloud to delete"
187
+ desc "delete", "Delete the cloud"
188
+ method_option :cloud, :type => :string, :aliases => "-c", :desc => "Specify cloud"
209
189
  def delete
210
- multiple_clouds(options[:cloud], "delete", "Select cloud to delete using:")
190
+ multiple_clouds(options[:cloud], "delete")
211
191
  say "You are about to delete application: #{@app.code_name}."
212
192
  say "Press Control-C at any moment to cancel."
213
193
  say "Please confirm each question by typing yes and pressing Enter."
@@ -224,18 +204,16 @@ module Shelly
224
204
  else
225
205
  say "Missing git remote"
226
206
  end
227
- rescue Client::APIError => e
228
- if e.not_found?
229
- say_error "You have no access to '#{@app.code_name}' cloud defined in Cloudfile"
230
- end
207
+ rescue Client::NotFoundException => e
208
+ raise unless e.resource == :cloud
209
+ say_error "You have no access to '#{@app.code_name}' cloud defined in Cloudfile"
231
210
  end
232
211
 
233
- desc "logs", "Show latest application logs from each instance"
234
- method_option :cloud, :type => :string, :aliases => "-c",
235
- :desc => "Specify which cloud to show logs for"
212
+ desc "logs", "Show latest application logs"
213
+ method_option :cloud, :type => :string, :aliases => "-c", :desc => "Specify cloud"
236
214
  def logs
237
215
  cloud = options[:cloud]
238
- multiple_clouds(cloud, "logs", "Select which to show logs for using:")
216
+ multiple_clouds(cloud, "logs")
239
217
  begin
240
218
  logs = @app.application_logs
241
219
  say "Cloud #{@app.code_name}:", :green
@@ -243,11 +221,39 @@ module Shelly
243
221
  say "Instance #{i+1}:", :green
244
222
  say log
245
223
  end
246
- rescue Client::APIError => e
247
- if e.not_found?
248
- say_error "You have no access to cloud '#{cloud || @app.code_name}'"
249
- end
224
+ rescue Client::NotFoundException => e
225
+ raise unless e.resource == :cloud
226
+ say_error "You have no access to '#{cloud || @app.code_name}' cloud defined in Cloudfile"
227
+ end
228
+ end
229
+
230
+ desc "logout", "Logout from Shelly Cloud"
231
+ def logout
232
+ user = Shelly::User.new
233
+ say "Your public SSH key has been removed from Shelly Cloud" if user.delete_ssh_key
234
+ say "You have been successfully logged out" if user.delete_credentials
235
+ end
236
+
237
+ desc "redeploy", "Redeploy application"
238
+ method_option :cloud, :type => :string, :aliases => "-c",
239
+ :desc => "Specify which cloud to redeploy application for"
240
+ def redeploy
241
+ multiple_clouds(options[:cloud], "redeploy")
242
+ @app.redeploy
243
+ say "Redeploying your application for cloud '#{@app}'", :green
244
+ rescue Client::ConflictException => e
245
+ case e[:state]
246
+ when "deploying", "configuring"
247
+ say_error "Your application is being redeployed at the moment"
248
+ when "no_code", "no_billing", "turned_off"
249
+ say_error "Cloud #{@app} is not running", :with_exit => false
250
+ say "Start your cloud with `shelly start --cloud #{@app}`"
251
+ exit 1
252
+ else raise
250
253
  end
254
+ rescue Client::NotFoundException => e
255
+ raise unless e.resource == :cloud
256
+ say_error "You have no access to '#{@app}' cloud defined in Cloudfile"
251
257
  end
252
258
 
253
259
  # FIXME: move to helpers
@@ -257,6 +263,7 @@ module Shelly
257
263
  unless ["code-name", "databases", "domains"].all? do |option|
258
264
  options.include?(option.to_s) && options[option.to_s] != option.to_s
259
265
  end && valid_databases?(options["databases"])
266
+ # FIXME: ' to `
260
267
  say_error "Try 'shelly help add' for more information"
261
268
  end
262
269
  end
@@ -302,7 +309,7 @@ module Shelly
302
309
  databases = ask("Unknown database kind. Supported are: #{kinds.join(", ")}:")
303
310
  end while not valid
304
311
 
305
- databases.empty? ? ["postgresql"] : databases
312
+ databases.empty? ? ["postgresql"] : databases - ["none"]
306
313
  end
307
314
 
308
315
  def info_adding_cloudfile_to_repository
@@ -17,8 +17,12 @@ module Shelly
17
17
 
18
18
  def start
19
19
  Shelly::CLI::Main.start(args)
20
- rescue => e
21
- raise e if debug?
20
+ rescue SystemExit; raise
21
+ rescue Interrupt
22
+ say_new_line
23
+ say_error "[canceled]"
24
+ rescue Exception
25
+ raise if debug?
22
26
  say_error "Unknown error, to see debug information run command with --debug"
23
27
  end
24
28
  end
@@ -7,7 +7,6 @@ module Shelly
7
7
  include Helpers
8
8
 
9
9
  before_hook :logged_in?, :only => [:list, :add]
10
- before_hook :inside_git_repository?, :only => [:list, :add]
11
10
  before_hook :cloudfile_present?, :only => [:list, :add]
12
11
 
13
12
  desc "list", "List users with access to clouds defined in Cloudfile"
@@ -18,12 +17,9 @@ module Shelly
18
17
  @app = App.new(cloud)
19
18
  say "Cloud #{cloud}:"
20
19
  @app.users.each { |user| say " #{user["email"]}" }
21
- rescue Client::APIError => e
22
- if e.not_found?
23
- say_error "You have no access to '#{cloud}' cloud defined in Cloudfile", :with_exit => false
24
- else
25
- say_error e.message, :with_exit => false
26
- end
20
+ rescue Client::NotFoundException => e
21
+ raise unless e.resource == :cloud
22
+ say_error "You have no access to '#{cloud}' cloud defined in Cloudfile"
27
23
  end
28
24
  end
29
25
  end
@@ -36,19 +32,17 @@ module Shelly
36
32
  @cloudfile.clouds.each do |cloud|
37
33
  begin
38
34
  @user.send_invitation(cloud, user_email)
39
- rescue Client::APIError => e
40
- if e.validation? && e.errors.include?(["email", "#{email} has already been taken"])
35
+ say "Sending invitation to #{user_email} to work on #{cloud}", :green
36
+ rescue Client::ValidationException => e
37
+ if e.errors.include?(["email", "#{email} has already been taken"])
41
38
  say_error "User #{email} is already in the cloud #{cloud}", :with_exit => false
42
- elsif e.not_found?
43
- say_error "You have no access to '#{cloud}' cloud defined in Cloudfile", :with_exit => false
44
- elsif e.validation?
39
+ else
45
40
  e.each_error { |error| say_error error, :with_exit => false }
46
41
  exit 1
47
- else
48
- say_error e.message, :with_exit => false
49
42
  end
50
- else
51
- say "Sending invitation to #{user_email} to work on #{cloud}", :green
43
+ rescue Client::NotFoundException => e
44
+ raise unless e.resource == :cloud
45
+ say_error "You have no access to '#{cloud}' cloud defined in Cloudfile"
52
46
  end
53
47
  end
54
48
  end
data/lib/shelly/client.rb CHANGED
@@ -4,41 +4,24 @@ require "cgi"
4
4
 
5
5
  module Shelly
6
6
  class Client
7
- class APIError < Exception
7
+ class APIException < Exception
8
8
  attr_reader :status_code, :body
9
9
 
10
- def initialize(status_code, body = {})
10
+ def initialize(body = {}, status_code = nil)
11
11
  @status_code = status_code
12
12
  @body = body
13
13
  end
14
14
 
15
- def message
16
- body["message"]
15
+ def [](key)
16
+ body[key.to_s]
17
17
  end
18
+ end
18
19
 
20
+ class UnauthorizedException < APIException; end
21
+ class ConflictException < APIException; end
22
+ class ValidationException < APIException
19
23
  def errors
20
- body["errors"]
21
- end
22
-
23
- def url
24
- body["url"]
25
- end
26
-
27
- def validation?
28
- message == "Validation Failed"
29
- end
30
-
31
- def not_found?
32
- status_code == 404
33
- end
34
-
35
- def resource_not_found
36
- return unless not_found?
37
- message =~ /Couldn't find (.*) with/ && $1.downcase.to_sym
38
- end
39
-
40
- def unauthorized?
41
- status_code == 401
24
+ self[:errors]
42
25
  end
43
26
 
44
27
  def each_error
@@ -47,6 +30,11 @@ module Shelly
47
30
  end
48
31
  end
49
32
  end
33
+ class NotFoundException < APIException
34
+ def resource
35
+ self[:resource].to_sym
36
+ end
37
+ end
50
38
 
51
39
  attr_reader :email, :password
52
40
 
@@ -104,7 +92,11 @@ module Shelly
104
92
  end
105
93
 
106
94
  def add_ssh_key(ssh_key)
107
- post("/ssh_key", :ssh_key => ssh_key)
95
+ post("/ssh_keys", :ssh_key => ssh_key)
96
+ end
97
+
98
+ def logout(ssh_key)
99
+ delete("/ssh_keys", :ssh_key => ssh_key)
108
100
  end
109
101
 
110
102
  def start_cloud(cloud)
@@ -124,15 +116,15 @@ module Shelly
124
116
  end
125
117
 
126
118
  def deploy_logs(cloud)
127
- get("/apps/#{cloud}/deploys")
119
+ get("/apps/#{cloud}/deployment_logs")
128
120
  end
129
121
 
130
122
  def deploy_log(cloud, log)
131
- get("/apps/#{cloud}/deploys/#{log}")
123
+ get("/apps/#{cloud}/deployment_logs/#{log}")
132
124
  end
133
125
 
134
126
  def application_logs(cloud)
135
- get("/apps/#{cloud}/logs")
127
+ get("/apps/#{cloud}/application_logs")
136
128
  end
137
129
 
138
130
  def database_backups(code_name)
@@ -159,6 +151,10 @@ module Shelly
159
151
  get("/apps/#{cloud}/users")
160
152
  end
161
153
 
154
+ def redeploy(cloud)
155
+ post("/apps/#{cloud}/deploys")
156
+ end
157
+
162
158
  def post(path, params = {})
163
159
  request(path, :post, params)
164
160
  end
@@ -220,10 +216,18 @@ module Shelly
220
216
  def process_response(response)
221
217
  body = JSON.parse(response.body) rescue JSON::ParserError && {}
222
218
  code = response.code
223
- raise APIError.new(code, body) if (400..599).include?(code)
219
+ if (400..599).include?(code)
220
+ exception_class = case response.code
221
+ when 401; UnauthorizedException
222
+ when 404; NotFoundException
223
+ when 409; ConflictException
224
+ when 422; ValidationException
225
+ else; APIException
226
+ end
227
+ raise exception_class.new(body, code)
228
+ end
224
229
  response.return!
225
230
  body
226
231
  end
227
232
  end
228
233
  end
229
-
@@ -6,7 +6,7 @@ module Shelly
6
6
  super("Progress", total)
7
7
  self.format_arguments = [:title, :percentage, :bar, :stat_for_file_transfer]
8
8
  end
9
-
9
+
10
10
  def progress_callback
11
11
  lambda { |size| inc(size) }
12
12
  end
@@ -63,19 +63,15 @@ module Shelly
63
63
  user = Shelly::User.new
64
64
  user.token
65
65
  user
66
- rescue Client::APIError => e
67
- if e.unauthorized?
68
- say_error "You are not logged in. To log in use:", :with_exit => false
69
- say " shelly login"
70
- exit 1
71
- end
66
+ rescue Client::UnauthorizedException
67
+ say_error "You are not logged in. To log in use: `shelly login`"
72
68
  end
73
69
 
74
- def multiple_clouds(cloud, action, message)
70
+ def multiple_clouds(cloud, action)
75
71
  clouds = Cloudfile.new.clouds
76
72
  if clouds.count > 1 && cloud.nil?
77
- say "You have multiple clouds in Cloudfile. #{message}"
78
- say " shelly #{action} --cloud #{clouds.first}"
73
+ say_error "You have multiple clouds in Cloudfile.", :with_exit => false
74
+ say "Select cloud using `shelly #{action} --cloud #{clouds.first}`"
79
75
  say "Available clouds:"
80
76
  clouds.each do |cloud|
81
77
  say " * #{cloud}"
@@ -85,6 +81,5 @@ module Shelly
85
81
  @app = Shelly::App.new
86
82
  @app.code_name = cloud || clouds.first
87
83
  end
88
-
89
84
  end
90
85
  end
data/lib/shelly/user.rb CHANGED
@@ -44,6 +44,14 @@ module Shelly
44
44
  set_credentials_permissions
45
45
  end
46
46
 
47
+ def delete_credentials
48
+ File.delete(credentials_path) if credentials_exists?
49
+ end
50
+
51
+ def delete_ssh_key
52
+ shelly.logout(File.read(ssh_key_path)) if ssh_key_exists?
53
+ end
54
+
47
55
  def ssh_key_exists?
48
56
  File.exists?(ssh_key_path)
49
57
  end
@@ -53,8 +61,8 @@ module Shelly
53
61
  end
54
62
 
55
63
  def ssh_key_registered?
56
- ssh_key = File.read(ssh_key_path).strip
57
- shelly.ssh_key_available?(ssh_key)
64
+ ssh_key = File.read(ssh_key_path).strip
65
+ shelly.ssh_key_available?(ssh_key)
58
66
  end
59
67
 
60
68
  def self.guess_email
@@ -1,3 +1,3 @@
1
1
  module Shelly
2
- VERSION = "0.0.43"
2
+ VERSION = "0.0.44.pre"
3
3
  end
data/lib/thor/thor.rb CHANGED
@@ -5,6 +5,10 @@ class Thor
5
5
  @hook[method] = options
6
6
  end
7
7
 
8
+ def hooks
9
+ @hook
10
+ end
11
+
8
12
  def send(*args)
9
13
  if args.first == :dispatch && !args[2].empty?
10
14
  running_task = args[2].first
data/shelly.gemspec CHANGED
@@ -16,8 +16,9 @@ Gem::Specification.new do |s|
16
16
  s.add_development_dependency "rake"
17
17
  s.add_development_dependency "guard"
18
18
  s.add_development_dependency "guard-rspec"
19
+ s.add_development_dependency "simplecov"
19
20
  if RUBY_PLATFORM =~ /darwin/
20
- s.add_development_dependency "growl_notify"
21
+ s.add_development_dependency "ruby_gntp"
21
22
  s.add_development_dependency "rb-fsevent"
22
23
  end
23
24
  s.add_development_dependency "fakefs"
data/spec/helpers.rb CHANGED
@@ -15,5 +15,12 @@ module RSpec
15
15
  def red(string)
16
16
  "\e[31m#{string}\e[0m"
17
17
  end
18
+
19
+ def hooks(model, method)
20
+ model.class.hooks.inject([]) do |result, v|
21
+ result << v[0] if v[1][:only].include?(method)
22
+ result
23
+ end
24
+ end
18
25
  end
19
26
  end
@@ -82,24 +82,24 @@ describe Shelly::App do
82
82
  @app.delete_config("path")
83
83
  end
84
84
  end
85
-
85
+
86
86
  describe "#attributes" do
87
87
  before do
88
88
  @response = {"web_server_ip" => "192.0.2.1", "mail_server_ip" => "192.0.2.3"}
89
89
  @client.stub(:app).and_return(@response)
90
90
  end
91
-
91
+
92
92
  it "should fetch app attributes from API and cache them" do
93
93
  @client.should_receive(:app).with("foo-staging").exactly(:once).and_return(@response)
94
94
  2.times { @app.attributes }
95
95
  end
96
-
96
+
97
97
  describe "#web_server_ip" do
98
98
  it "should return web server ip address" do
99
99
  @app.web_server_ip.should == "192.0.2.1"
100
100
  end
101
101
  end
102
-
102
+
103
103
  describe "#mail_server_ip" do
104
104
  it "should return mail server ip address" do
105
105
  @app.mail_server_ip.should == "192.0.2.3"
@@ -280,6 +280,13 @@ config
280
280
  end
281
281
  end
282
282
  end
283
+
284
+ describe "#redeploy" do
285
+ it "should redeploy app via API" do
286
+ @client.should_receive(:redeploy).with("foo-staging")
287
+ @app.redeploy
288
+ end
289
+ end
283
290
 
284
291
  describe "#to_s" do
285
292
  it "should return code_name" do
@@ -287,4 +294,3 @@ config
287
294
  end
288
295
  end
289
296
  end
290
-