shelly 0.1.34 → 0.1.35
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.
- 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
|