shelly 0.1.34 → 0.1.35
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +14 -0
- data/lib/shelly.rb +1 -0
- data/lib/shelly/app.rb +4 -15
- data/lib/shelly/cli/main.rb +11 -0
- data/lib/shelly/cli/organization.rb +35 -0
- data/lib/shelly/cli/user.rb +70 -22
- data/lib/shelly/client.rb +18 -7
- data/lib/shelly/organization.rb +45 -0
- data/lib/shelly/user.rb +8 -8
- data/lib/shelly/version.rb +1 -1
- data/spec/shelly/app_spec.rb +2 -8
- data/spec/shelly/cli/main_spec.rb +53 -25
- data/spec/shelly/cli/organization_spec.rb +44 -0
- data/spec/shelly/cli/user_spec.rb +105 -49
- data/spec/shelly/client_spec.rb +33 -7
- data/spec/shelly/organization_spec.rb +78 -0
- data/spec/shelly/user_spec.rb +9 -15
- metadata +41 -115
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## 0.1.34 / 2012-12-06
|
2
|
+
|
3
|
+
* [feature] Support for organizations
|
4
|
+
|
5
|
+
* [feature] New cloud can be created with existing organizatino with --organization [-o] option
|
6
|
+
|
7
|
+
Usage: ```shelly add --organization=ORGANIZATION_NAME```
|
8
|
+
|
9
|
+
* Manage users within organization
|
10
|
+
|
11
|
+
All ```shelly user``` commands affected
|
12
|
+
|
13
|
+
* [feature] Show organizations with associated clouds
|
14
|
+
|
1
15
|
## 0.1.34 / 2012-11-11
|
2
16
|
|
3
17
|
* [feature] Accept DSA keys when logging in or registering
|
data/lib/shelly.rb
CHANGED
@@ -13,6 +13,7 @@ require "shelly/model"
|
|
13
13
|
|
14
14
|
module Shelly
|
15
15
|
autoload :App, "shelly/app"
|
16
|
+
autoload :Organization, "shelly/organization"
|
16
17
|
autoload :Cloudfile, "shelly/cloudfile"
|
17
18
|
autoload :Client, "shelly/client"
|
18
19
|
autoload :StructureValidator, "shelly/structure_validator"
|
data/lib/shelly/app.rb
CHANGED
@@ -10,7 +10,7 @@ module Shelly
|
|
10
10
|
|
11
11
|
attr_accessor :code_name, :databases, :ruby_version, :environment,
|
12
12
|
:git_url, :domains, :web_server_ip, :size, :thin, :redeem_code,
|
13
|
-
:content
|
13
|
+
:content, :organization
|
14
14
|
|
15
15
|
def initialize(code_name = nil, content = nil)
|
16
16
|
self.code_name = code_name
|
@@ -43,7 +43,9 @@ module Shelly
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def create
|
46
|
-
attributes = {:code_name => code_name,
|
46
|
+
attributes = {:code_name => code_name,
|
47
|
+
:redeem_code => redeem_code,
|
48
|
+
:organization_name => organization}
|
47
49
|
response = shelly.create_app(attributes)
|
48
50
|
self.git_url = response["git_url"]
|
49
51
|
self.domains = response["domains"]
|
@@ -132,19 +134,6 @@ module Shelly
|
|
132
134
|
"#{File.basename(Dir.pwd)}-#{guessed || 'staging'}".downcase.dasherize
|
133
135
|
end
|
134
136
|
|
135
|
-
def collaborations
|
136
|
-
@collaborations ||= Array(shelly.collaborations(code_name)).
|
137
|
-
sort_by { |c| c["email"] }
|
138
|
-
end
|
139
|
-
|
140
|
-
def active_collaborations
|
141
|
-
collaborations.select { |c| c["active"] }
|
142
|
-
end
|
143
|
-
|
144
|
-
def inactive_collaborations
|
145
|
-
collaborations.select { |c| !c["active"] }
|
146
|
-
end
|
147
|
-
|
148
137
|
def configs
|
149
138
|
@configs ||= shelly.app_configs(code_name)
|
150
139
|
end
|
data/lib/shelly/cli/main.rb
CHANGED
@@ -5,6 +5,7 @@ require "shelly/cli/backup"
|
|
5
5
|
require "shelly/cli/deploy"
|
6
6
|
require "shelly/cli/config"
|
7
7
|
require "shelly/cli/file"
|
8
|
+
require "shelly/cli/organization"
|
8
9
|
|
9
10
|
module Shelly
|
10
11
|
module CLI
|
@@ -14,6 +15,7 @@ module Shelly
|
|
14
15
|
register_subcommand(Deploy, "deploy", "deploy <command>", "View deploy logs")
|
15
16
|
register_subcommand(Config, "config", "config <command>", "Manage application configuration files")
|
16
17
|
register_subcommand(File, "file", "file <command>", "Upload and download files to and from persistent storage")
|
18
|
+
register_subcommand(Organization, "organization", "organization <command>", "View organizations")
|
17
19
|
|
18
20
|
check_unknown_options!(:except => :rake)
|
19
21
|
|
@@ -79,6 +81,8 @@ module Shelly
|
|
79
81
|
:desc => "Server size [large, small]"
|
80
82
|
method_option "redeem-code", :type => :string, :aliases => "-r",
|
81
83
|
:desc => "Redeem code for free credits"
|
84
|
+
method_option "organization", :type => :string, :aliases => "-o",
|
85
|
+
:desc => "Add cloud to existing organization"
|
82
86
|
method_option "skip-requirements-check", :type => :boolean,
|
83
87
|
:desc => "Skip Shelly Cloud requirements check"
|
84
88
|
desc "add", "Add a new cloud"
|
@@ -92,6 +96,7 @@ module Shelly
|
|
92
96
|
app.databases = options["databases"] || ask_for_databases
|
93
97
|
app.size = options["size"] || "large"
|
94
98
|
app.redeem_code = options["redeem-code"]
|
99
|
+
app.organization = options["organization"]
|
95
100
|
app.create
|
96
101
|
|
97
102
|
if overwrite_remote?(app)
|
@@ -120,6 +125,12 @@ module Shelly
|
|
120
125
|
say_new_line
|
121
126
|
say_error "Fix erros in the below command and type it again to create your cloud" , :with_exit => false
|
122
127
|
say_error "shelly add --code-name=#{app.code_name.downcase.dasherize} --databases=#{app.databases.join(',')} --size=#{app.size}"
|
128
|
+
rescue Client::ForbiddenException
|
129
|
+
say_error "You have to be the owner of '#{options[:organization]}' organization to add clouds"
|
130
|
+
rescue Client::NotFoundException => e
|
131
|
+
raise unless e.resource == :organization
|
132
|
+
say_error "Organization '#{options[:organization]}' not found", :with_exit => false
|
133
|
+
say_error "You can list organizations you have access to with `shelly organization list`"
|
123
134
|
end
|
124
135
|
|
125
136
|
map "status" => :list
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "shelly/cli/command"
|
2
|
+
|
3
|
+
module Shelly
|
4
|
+
module CLI
|
5
|
+
class Organization < Command
|
6
|
+
namespace :organization
|
7
|
+
include Helpers
|
8
|
+
|
9
|
+
before_hook :logged_in?, :only => [:list]
|
10
|
+
|
11
|
+
desc "list", "Lists organizations"
|
12
|
+
def list
|
13
|
+
user = Shelly::User.new
|
14
|
+
organizations = user.organizations
|
15
|
+
say "You have access to the following organizations and clouds:", :green
|
16
|
+
say_new_line
|
17
|
+
organizations.each do |organization|
|
18
|
+
say organization.name, :green
|
19
|
+
if organization.apps.present?
|
20
|
+
apps_table = organization.apps.map do |app|
|
21
|
+
state = app.state
|
22
|
+
msg = if state == "deploy_failed" || state == "configuration_failed"
|
23
|
+
" (deployment log: `shelly deploys show last -c #{app["code_name"]}`)"
|
24
|
+
end
|
25
|
+
[app.to_s, "| #{state.humanize}#{msg}"]
|
26
|
+
end
|
27
|
+
print_table(apps_table, :ident => 2, :colwidth => 35)
|
28
|
+
else
|
29
|
+
print_wrapped "No clouds", :ident => 2
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/shelly/cli/user.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "shelly/cli/command"
|
2
|
+
require "shelly/cli/organization"
|
2
3
|
|
3
4
|
module Shelly
|
4
5
|
module CLI
|
@@ -7,46 +8,93 @@ module Shelly
|
|
7
8
|
include Helpers
|
8
9
|
|
9
10
|
before_hook :logged_in?, :only => [:list, :add, :delete]
|
10
|
-
class_option :cloud, :type => :string, :aliases => "-c", :desc => "Specify cloud"
|
11
11
|
|
12
|
-
desc "list", "List users with access to
|
12
|
+
desc "list", "List users with access to organizations"
|
13
13
|
def list
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
user = Shelly::User.new
|
15
|
+
organizations = user.organizations
|
16
|
+
|
17
|
+
say "Organizations with users:"
|
18
|
+
|
19
|
+
organizations.each do |organization|
|
20
|
+
say " #{organization.name}", :green
|
21
|
+
if organization.memberships.present?
|
22
|
+
members_table = organization.owners.map { |owner| [owner["email"], " | owner"] }
|
23
|
+
members_table += organization.members.map { |member| [member["email"], " | member"] }
|
24
|
+
members_table += organization.inactive_members.map { |inactive| [inactive["email"] + " (invited)", " | #{humman_owner(inactive["owner"])}"] }
|
25
|
+
print_table(members_table, :ident => 4, :colwidth => 45)
|
26
|
+
say_new_line
|
27
|
+
end
|
28
|
+
end
|
19
29
|
end
|
20
30
|
|
21
|
-
|
31
|
+
method_option :organization, :type => :string, :aliases => "-o", :desc => "Specify organization"
|
32
|
+
desc "add [EMAIL]", "Add new developer to organization"
|
22
33
|
def add(email = nil)
|
23
|
-
|
24
|
-
|
34
|
+
organization = organization_present?(options[:organization], "user add [EMAIL]")
|
35
|
+
|
25
36
|
user_email = email || ask_for_email({:guess_email => false})
|
26
|
-
user
|
27
|
-
|
37
|
+
owner = yes?("Should this user have owner privileges? (yes/no)")
|
38
|
+
organization.send_invitation(user_email, owner)
|
39
|
+
|
40
|
+
say "Sending invitation to #{user_email} to work on #{organization} organization", :green
|
41
|
+
rescue Client::ForbiddenException
|
42
|
+
say_error "You have to be organization's owner to add new members"
|
43
|
+
rescue Client::NotFoundException => e
|
44
|
+
raise unless e.resource == :organization
|
45
|
+
say_error "Organization '#{options[:organization]}' not found", :with_exit => false
|
46
|
+
say_error "You can list organizations you have access to with `shelly organization list`"
|
28
47
|
rescue Client::ValidationException => e
|
29
|
-
if e.errors.include?(["email", "#{email} has already
|
30
|
-
say_error "User #{email} is already in the
|
48
|
+
if e.errors.include?(["email", "#{email} has been already taken"])
|
49
|
+
say_error "User #{email} is already in the organization #{organization}"
|
31
50
|
else
|
32
51
|
e.each_error { |error| say_error error, :with_exit => false }
|
33
52
|
exit 1
|
34
53
|
end
|
35
54
|
end
|
36
55
|
|
37
|
-
|
56
|
+
method_option :organization, :type => :string, :aliases => "-o", :desc => "Specify organization"
|
57
|
+
desc "delete [EMAIL]", "Remove developer from organization"
|
38
58
|
def delete(email = nil)
|
39
|
-
|
40
|
-
|
59
|
+
organization = organization_present?(options[:organization], "user delete [EMAIL]")
|
60
|
+
|
41
61
|
user_email = email || ask_for_email({:guess_email => false})
|
42
|
-
|
43
|
-
|
62
|
+
organization.delete_member(user_email)
|
63
|
+
|
64
|
+
say "User #{user_email} deleted from organization #{organization}"
|
65
|
+
rescue Client::ForbiddenException
|
66
|
+
say_error "You have to be organization's owner to remove members"
|
44
67
|
rescue Client::ConflictException => e
|
45
68
|
say_error e[:message]
|
46
69
|
rescue Client::NotFoundException => e
|
47
|
-
|
48
|
-
|
49
|
-
|
70
|
+
if e.resource == :user
|
71
|
+
say_error "User '#{user_email}' not found", :with_exit => false
|
72
|
+
say_error "You can list users with `shelly user list`"
|
73
|
+
elsif e.resource == :organization
|
74
|
+
say_error "Organization '#{options[:organization]}' not found", :with_exit => false
|
75
|
+
say_error "You can list organizations you have access to with `shelly organization list`"
|
76
|
+
else
|
77
|
+
raise
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
no_tasks do
|
82
|
+
def humman_owner(owner)
|
83
|
+
owner ? "owner" : "member"
|
84
|
+
end
|
85
|
+
|
86
|
+
def organization_present?(name, action)
|
87
|
+
unless name
|
88
|
+
say_error "You have to specify organization", :with_exit => false
|
89
|
+
say "Select organization using `shelly #{action} --organization ORGANIZATION_NAME`"
|
90
|
+
Shelly::CLI::Organization.new.list
|
91
|
+
exit 1
|
92
|
+
else
|
93
|
+
Shelly::Organization.new("name" => name).tap do |org|
|
94
|
+
org.members
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
50
98
|
end
|
51
99
|
end
|
52
100
|
end
|
data/lib/shelly/client.rb
CHANGED
@@ -19,6 +19,7 @@ module Shelly
|
|
19
19
|
end
|
20
20
|
|
21
21
|
class UnauthorizedException < APIException; end
|
22
|
+
class ForbiddenException < APIException; end
|
22
23
|
class ConflictException < APIException; end
|
23
24
|
class GemVersionException < APIException; end
|
24
25
|
class GatewayTimeoutException < APIException; end
|
@@ -87,16 +88,17 @@ module Shelly
|
|
87
88
|
delete("/apps/#{cloud}/configs/#{CGI.escape(path)}")
|
88
89
|
end
|
89
90
|
|
90
|
-
def send_invitation(
|
91
|
-
post("/
|
91
|
+
def send_invitation(name, email, owner = false)
|
92
|
+
post("/organizations/#{name}/memberships", :email => email, :owner => owner)
|
92
93
|
end
|
93
94
|
|
94
|
-
def
|
95
|
-
delete("/
|
95
|
+
def delete_member(name, email)
|
96
|
+
delete("/organizations/#{name}/memberships/#{email}")
|
96
97
|
end
|
97
98
|
|
98
99
|
def create_app(attributes)
|
99
|
-
|
100
|
+
organization = attributes.delete(:organization_name)
|
101
|
+
post("/apps", :app => attributes, :organization_name => organization)
|
100
102
|
end
|
101
103
|
|
102
104
|
def delete_app(code_name)
|
@@ -127,6 +129,14 @@ module Shelly
|
|
127
129
|
get("/apps/#{code_name}")
|
128
130
|
end
|
129
131
|
|
132
|
+
def organizations
|
133
|
+
get("/organizations")
|
134
|
+
end
|
135
|
+
|
136
|
+
def organization(name)
|
137
|
+
get("/organizations/#{name}")
|
138
|
+
end
|
139
|
+
|
130
140
|
def statistics(code_name)
|
131
141
|
get("/apps/#{code_name}/statistics")
|
132
142
|
end
|
@@ -167,8 +177,8 @@ module Shelly
|
|
167
177
|
post("/apps/#{code_name}/database_backups", :kind => kind)
|
168
178
|
end
|
169
179
|
|
170
|
-
def
|
171
|
-
get("/
|
180
|
+
def members(name)
|
181
|
+
get("/organizations/#{name}/memberships")
|
172
182
|
end
|
173
183
|
|
174
184
|
def redeploy(cloud)
|
@@ -244,6 +254,7 @@ module Shelly
|
|
244
254
|
if (400..599).include?(code)
|
245
255
|
exception_class = case response.code
|
246
256
|
when 401; UnauthorizedException
|
257
|
+
when 403; ForbiddenException
|
247
258
|
when 404; NotFoundException
|
248
259
|
when 409; ConflictException
|
249
260
|
when 412; GemVersionException
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Shelly
|
2
|
+
class Organization < Model
|
3
|
+
attr_reader :name, :app_code_names
|
4
|
+
|
5
|
+
def initialize(attributes = {})
|
6
|
+
@name = attributes["name"]
|
7
|
+
@app_code_names = attributes["app_code_names"]
|
8
|
+
end
|
9
|
+
|
10
|
+
def apps
|
11
|
+
app_code_names.map do |code_name|
|
12
|
+
Shelly::App.new(code_name)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def memberships
|
17
|
+
@members ||= Array(shelly.members(name)).
|
18
|
+
sort_by { |c| c["email"] }
|
19
|
+
end
|
20
|
+
|
21
|
+
def owners
|
22
|
+
memberships.select { |c| c["owner"] } - inactive_members
|
23
|
+
end
|
24
|
+
|
25
|
+
def members
|
26
|
+
memberships.select { |c| !c["owner"] } - inactive_members
|
27
|
+
end
|
28
|
+
|
29
|
+
def inactive_members
|
30
|
+
memberships.select { |c| !c["active"] }
|
31
|
+
end
|
32
|
+
|
33
|
+
def send_invitation(email, owner)
|
34
|
+
shelly.send_invitation(name, email, owner)
|
35
|
+
end
|
36
|
+
|
37
|
+
def delete_member(email)
|
38
|
+
shelly.delete_member(name, email)
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_s
|
42
|
+
name
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/shelly/user.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'shelly/organization'
|
2
|
+
|
1
3
|
module Shelly
|
2
4
|
class User < Model
|
3
5
|
attr_accessor :email, :password
|
@@ -11,6 +13,12 @@ module Shelly
|
|
11
13
|
shelly.apps
|
12
14
|
end
|
13
15
|
|
16
|
+
def organizations
|
17
|
+
shelly.organizations.map do |attributes|
|
18
|
+
Shelly::Organization.new(attributes)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
14
22
|
def register
|
15
23
|
ssh_key = File.read(ssh_key_path) if ssh_key_exists?
|
16
24
|
shelly.register_user(email, password, ssh_key)
|
@@ -29,14 +37,6 @@ module Shelly
|
|
29
37
|
shelly.token["token"]
|
30
38
|
end
|
31
39
|
|
32
|
-
def send_invitation(cloud, email)
|
33
|
-
shelly.send_invitation(cloud, email)
|
34
|
-
end
|
35
|
-
|
36
|
-
def delete_collaboration(cloud, email)
|
37
|
-
shelly.delete_collaboration(cloud, email)
|
38
|
-
end
|
39
|
-
|
40
40
|
def load_credentials
|
41
41
|
return unless credentials_exists?
|
42
42
|
@email, @password = File.read(credentials_path).split("\n")
|
data/lib/shelly/version.rb
CHANGED
data/spec/shelly/app_spec.rb
CHANGED
@@ -47,13 +47,6 @@ describe Shelly::App do
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
describe "#collaborations" do
|
51
|
-
it "should fetch app's users" do
|
52
|
-
@client.should_receive(:collaborations).with("foo-staging")
|
53
|
-
@app.collaborations
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
50
|
describe "#add_git_remote" do
|
58
51
|
before do
|
59
52
|
@app.stub(:git_url).and_return("git@git.shellycloud.com:foo-staging.git")
|
@@ -283,7 +276,8 @@ describe Shelly::App do
|
|
283
276
|
@app.redeem_code = "foo123"
|
284
277
|
attributes = {
|
285
278
|
:code_name => "fooo",
|
286
|
-
:redeem_code => "foo123"
|
279
|
+
:redeem_code => "foo123",
|
280
|
+
:organization_name => nil
|
287
281
|
}
|
288
282
|
@client.should_receive(:create_app).with(attributes).and_return("git_url" => "git@git.shellycloud.com:fooo.git",
|
289
283
|
"domains" => %w(fooo.shellyapp.com))
|
@@ -27,29 +27,30 @@ describe Shelly::CLI::Main do
|
|
27
27
|
it "should display available commands" do
|
28
28
|
out = IO.popen("bin/shelly --debug").read.strip
|
29
29
|
out.should include("Tasks:")
|
30
|
-
out.should include("shelly add
|
31
|
-
out.should include("shelly backup <command>
|
32
|
-
out.should include("shelly check
|
33
|
-
out.should include("shelly config <command>
|
34
|
-
out.should include("shelly console
|
35
|
-
out.should include("shelly dbconsole
|
36
|
-
out.should include("shelly delete
|
37
|
-
out.should include("shelly deploy <command>
|
38
|
-
out.should include("shelly file <command>
|
39
|
-
out.should include("shelly help [TASK]
|
40
|
-
out.should include("shelly info
|
41
|
-
out.should include("shelly list
|
42
|
-
out.should include("shelly login [EMAIL]
|
43
|
-
out.should include("shelly logout
|
44
|
-
out.should include("shelly logs
|
45
|
-
out.should include("shelly open
|
46
|
-
out.should include("shelly
|
47
|
-
out.should include("shelly
|
48
|
-
out.should include("shelly
|
49
|
-
out.should include("shelly
|
50
|
-
out.should include("shelly
|
51
|
-
out.should include("shelly
|
52
|
-
out.should include("shelly
|
30
|
+
out.should include("shelly add # Add a new cloud")
|
31
|
+
out.should include("shelly backup <command> # Manage database backups")
|
32
|
+
out.should include("shelly check # Check if application fulfills Shelly Cloud requirements")
|
33
|
+
out.should include("shelly config <command> # Manage application configuration files")
|
34
|
+
out.should include("shelly console # Open application console")
|
35
|
+
out.should include("shelly dbconsole # Run rails dbconsole")
|
36
|
+
out.should include("shelly delete # Delete the cloud")
|
37
|
+
out.should include("shelly deploy <command> # View deploy logs")
|
38
|
+
out.should include("shelly file <command> # Upload and download files to and from persistent storage")
|
39
|
+
out.should include("shelly help [TASK] # Describe available tasks or one specific task")
|
40
|
+
out.should include("shelly info # Show basic information about cloud")
|
41
|
+
out.should include("shelly list # List available clouds")
|
42
|
+
out.should include("shelly login [EMAIL] # Log into Shelly Cloud")
|
43
|
+
out.should include("shelly logout # Logout from Shelly Cloud")
|
44
|
+
out.should include("shelly logs # Show latest application logs")
|
45
|
+
out.should include("shelly open # Open application page in browser")
|
46
|
+
out.should include("shelly organization <command> # View organizations")
|
47
|
+
out.should include("shelly rake TASK # Run rake task")
|
48
|
+
out.should include("shelly redeploy # Redeploy application")
|
49
|
+
out.should include("shelly register [EMAIL] # Register new account")
|
50
|
+
out.should include("shelly setup # Set up git remotes for deployment on Shelly Cloud")
|
51
|
+
out.should include("shelly start # Start the cloud")
|
52
|
+
out.should include("shelly stop # Shutdown the cloud")
|
53
|
+
out.should include("shelly user <command> # Manage collaborators")
|
53
54
|
out.should include("Options")
|
54
55
|
out.should include("[--debug] # Show debug information")
|
55
56
|
out.should include("-h, [--help] # Describe available tasks or one specific task")
|
@@ -531,18 +532,45 @@ More info at http://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository\e[0m
|
|
531
532
|
invoke(@main, :add)
|
532
533
|
end
|
533
534
|
end
|
535
|
+
|
536
|
+
it "should show forbidden exception" do
|
537
|
+
@main.options = {:organization => "foo"}
|
538
|
+
exception = Shelly::Client::ForbiddenException.new
|
539
|
+
@app.should_receive(:create).and_raise(exception)
|
540
|
+
$stdout.should_receive(:puts).with(red "You have to be the owner of 'foo' organization to add clouds")
|
541
|
+
|
542
|
+
expect do
|
543
|
+
fake_stdin(["foooo", "none"]) do
|
544
|
+
invoke(@main, :add)
|
545
|
+
end
|
546
|
+
end.to raise_error(SystemExit)
|
547
|
+
end
|
548
|
+
|
549
|
+
it "should show that organization was not found" do
|
550
|
+
@main.options = {:organization => "foo"}
|
551
|
+
response = {"resource" => "organization"}
|
552
|
+
exception = Shelly::Client::NotFoundException.new(response)
|
553
|
+
@app.should_receive(:create).and_raise(exception)
|
554
|
+
$stdout.should_receive(:puts).with(red "Organization 'foo' not found")
|
555
|
+
$stdout.should_receive(:puts).with(red "You can list organizations you have access to with `shelly organization list`")
|
556
|
+
|
557
|
+
expect do
|
558
|
+
fake_stdin(["foooo", "none"]) do
|
559
|
+
invoke(@main, :add)
|
560
|
+
end
|
561
|
+
end.to raise_error(SystemExit)
|
562
|
+
end
|
563
|
+
|
534
564
|
end
|
535
565
|
|
536
566
|
describe "#list" do
|
537
567
|
before do
|
538
|
-
@user = Shelly::User.new
|
539
568
|
@client.stub(:token).and_return("abc")
|
540
569
|
@client.stub(:apps).and_return([
|
541
570
|
{"code_name" => "abc", "state" => "running"},
|
542
571
|
{"code_name" => "fooo", "state" => "deploy_failed"},
|
543
572
|
{"code_name" => "bar", "state" => "configuration_failed"}
|
544
573
|
])
|
545
|
-
Shelly::User.stub(:new).and_return(@user)
|
546
574
|
end
|
547
575
|
|
548
576
|
it "should ensure user has logged in" do
|