shelly 0.4.42 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bd0f3635267e3be6e9d6fbff86054582b6ac3b9f
4
- data.tar.gz: 63d62d167f8245525f44a317e39d72529f1a0037
3
+ metadata.gz: 4b85bcd0e7111d1a7bdaf59a47384141a49fb347
4
+ data.tar.gz: c0279a7748d978b1cb427240b4b0c9a49dbbd039
5
5
  SHA512:
6
- metadata.gz: 7c4780ffcc4713f920354d5e7a4c9a8421b51382a956f3b0acea83023d28c016fe2a7cb1091093464ec8799d4963ed4c2a3b2f14a6d2d73233d85d332bb29593
7
- data.tar.gz: 7dee1731a302343f71c175fe6dc87695639d21e55f77ee1d8b8a77d95d7f75a65a3ff11ddf61b4d1822422cae98877194eb9de834d1d7fb5acf3c65c94f20b51
6
+ metadata.gz: 72a140d37c0f1027109b1a066e9ac6b9c4e8c785be895e46c3225b8b9c92f166b15ba72fc85439137bb3f0de2c18cfd0489d76b8a82085fe8d9bafd05a12409d
7
+ data.tar.gz: a9c4dc381a59cd781993d8a319767552ea013eea3aace1fead433a14a369cbe58f636baadc2db18cc5d3ce32ad156e2dce5868a62f49011ab5bed84e6165f6f5
@@ -1,4 +1,5 @@
1
1
  rvm:
2
+ - '2.2'
2
3
  - '2.1'
3
4
  - 2.0.0
4
5
  - 1.9.3
@@ -1,3 +1,12 @@
1
+ ## 0.5.0 / 2015-01-02
2
+
3
+ * [bugfix] Catch Conflict 409 when creating or updating endpoints
4
+ * [improvement] shelly info should print cloud region
5
+ * [improvement] shelly add should ask about organization name instead of number
6
+ from the list
7
+ * [improvement] Replaced zone with region
8
+ * [improvement] Allow user to choose region for the new cloud
9
+
1
10
  ## 0.4.42 / 2014-12-14
2
11
 
3
12
  * [improvement] Added --server / -s option for shelly rake command, so user
@@ -11,10 +11,11 @@ module Shelly
11
11
  DATABASE_KINDS = %w(postgresql mysql mongodb redis)
12
12
  DATABASE_CHOICES = DATABASE_KINDS + %w(none)
13
13
  SERVER_SIZES = %w(small large)
14
+ REGIONS = %w(EU NA)
14
15
 
15
16
  attr_accessor :code_name, :databases, :ruby_version, :environment,
16
17
  :git_url, :domains, :web_server_ip, :size, :thin,
17
- :organization_name, :zone, :usage, :traffic
18
+ :organization_name, :zone, :region, :usage, :traffic
18
19
 
19
20
  def initialize(code_name = nil)
20
21
  self.code_name = code_name
@@ -71,7 +72,8 @@ module Shelly
71
72
  def create
72
73
  attributes = {:code_name => code_name,
73
74
  :organization_name => organization_name,
74
- :zone => zone}
75
+ :zone => zone,
76
+ :region => @region}
75
77
  response = shelly.create_app(attributes)
76
78
  assign_attributes(response)
77
79
  end
@@ -279,6 +281,10 @@ module Shelly
279
281
  attributes["git_info"]
280
282
  end
281
283
 
284
+ def region
285
+ attributes['region'] || @region
286
+ end
287
+
282
288
  def state
283
289
  attributes["state"]
284
290
  end
@@ -52,7 +52,7 @@ module Shelly
52
52
  def create(path)
53
53
  app = multiple_clouds(options[:cloud], "create #{path}")
54
54
  if app.config_exists?(path)
55
- say "File '#{path}' already exists. Use `shelly config edit #{path} --cloud #{options[:cloud]}` to update it.", :red
55
+ say "File '#{path}' already exists. Use `shelly config edit #{path} --cloud #{app}` to update it.", :red
56
56
  else
57
57
  output = open_editor(path)
58
58
  app.create_config(path, output)
@@ -34,7 +34,6 @@ module Shelly
34
34
  end
35
35
 
36
36
  print_table(to_display, :ident => 2)
37
-
38
37
  else
39
38
  say "No HTTP endpoints available"
40
39
  end
@@ -81,6 +80,18 @@ module Shelly
81
80
  app = multiple_clouds(options[:cloud],
82
81
  "endpoint create [CERT_PATH] [KEY_PATH] [BUNDLE_PATH]")
83
82
 
83
+ say "Every unique IP address assigned to endpoint costs 10€/month"
84
+ say "It's required for SSL/TLS"
85
+ if cert_path == nil && key_path == nil
86
+ say "You didn't provide certificate but it can be added later"
87
+ say "Assigned IP address can be used to catch all domains pointing to that address, without SSL/TLS enabled"
88
+ exit(0) unless yes?("Are you sure you want to create endpoint without certificate (yes/no):")
89
+ elsif app.endpoints.count > 0
90
+ ask_if_endpoints_were_already_created(app)
91
+ else
92
+ exit(0) unless yes?("Are you sure you want to create endpoint? (yes/no):")
93
+ end
94
+
84
95
  certificate, key = read_certificate_components(cert_path, key_path,
85
96
  bundle_path)
86
97
 
@@ -94,6 +105,8 @@ module Shelly
94
105
  say "Private IP address was requested for your cloud."
95
106
  say "Support has been notified and will contact you shortly."
96
107
  end
108
+ rescue Client::ConflictException => e
109
+ say_error e['message']
97
110
  rescue Client::ValidationException => e
98
111
  e.each_error { |error| say_error error, :with_exit => false }
99
112
  exit 1
@@ -127,6 +140,8 @@ module Shelly
127
140
  rescue Client::ValidationException => e
128
141
  e.each_error { |error| say_error error, :with_exit => false }
129
142
  exit 1
143
+ rescue Client::ConflictException => e
144
+ say_error e['message']
130
145
  rescue Client::NotFoundException => e
131
146
  raise unless e.resource == :certificate
132
147
  say_error "Endpoint not found"
@@ -168,6 +183,16 @@ module Shelly
168
183
  [certificate, key]
169
184
  end
170
185
  end
186
+
187
+ def ask_if_endpoints_were_already_created(app)
188
+ cli = Shelly::CLI::Endpoint.new
189
+ cli.options = {:cloud => app}
190
+ cli.list
191
+ say_new_line
192
+ exit(0) unless yes?("You already have assigned endpoint(s). Are " \
193
+ "you sure you want to create another one with a new IP address? " \
194
+ "(yes/no):")
195
+ end
171
196
  end
172
197
  end
173
198
  end
@@ -111,6 +111,7 @@ module Shelly
111
111
  app = multiple_clouds(options[:cloud], "info")
112
112
  msg = info_show_last_deploy_logs(app)
113
113
  say "Cloud #{app}:", app.in_deploy_failed_state? ? :red : :green
114
+ print_wrapped "Region: #{app.region}", :ident => 2
114
115
  print_wrapped "State: #{app.state_description}#{msg}", :ident => 2
115
116
  say_new_line
116
117
  print_wrapped "Deployed commit sha: #{app.git_info["deployed_commit_sha"]}", :ident => 2
@@ -17,6 +17,8 @@ module Shelly
17
17
  :desc => "Skip Shelly Cloud requirements check"
18
18
  method_option "zone", :type => :string, :hide => true,
19
19
  :desc => "Create cloud in given zone"
20
+ method_option "region", :type => :string,
21
+ :desc => "Create cloud in given region"
20
22
  desc "add", "Add a new cloud"
21
23
  def add
22
24
  check_options(options)
@@ -27,8 +29,13 @@ module Shelly
27
29
  app.code_name = options["code-name"] || ask_for_code_name
28
30
  app.databases = options["databases"] || ask_for_databases
29
31
  app.size = options["size"] || "small"
30
- app.organization_name = options["organization"] || ask_for_organization(options)
31
- app.zone = options["zone"]
32
+ app.organization_name = options["organization"] ||
33
+ ask_for_organization(options)
34
+ if options["zone"].present?
35
+ app.zone = options["zone"]
36
+ else
37
+ app.region = options["region"] || ask_for_region
38
+ end
32
39
 
33
40
  app.create
34
41
  say "Cloud '#{app}' created in '#{app.organization_name}' organization", :green
@@ -60,7 +67,7 @@ module Shelly
60
67
  e.each_error { |error| say_error error, :with_exit => false }
61
68
  say_new_line
62
69
  say_error "Fix erros in the below command and type it again to create your cloud" , :with_exit => false
63
- say_error "shelly add --code-name=#{app.code_name.downcase.dasherize} --databases=#{app.databases.join(',')} --organization=#{app.organization_name} --size=#{app.size}"
70
+ say_error "shelly add --code-name=#{app.code_name.downcase.dasherize} --databases=#{app.databases.join(',')} --organization=#{app.organization_name} --size=#{app.size} --region=#{app.region}"
64
71
  rescue Client::ForbiddenException
65
72
  say_error "You have to be the owner of '#{app.organization_name}' organization to add clouds"
66
73
  rescue Client::NotFoundException => e
@@ -72,33 +79,33 @@ module Shelly
72
79
  no_tasks do
73
80
  def ask_for_organization(options)
74
81
  organizations = Shelly::User.new.organizations
82
+
75
83
  if organizations.blank?
76
84
  ask_for_new_organization(options)
77
85
  else
78
- count = organizations.count
79
- option_selected = 0
86
+ say "Select organization for this cloud:"
87
+ say_new_line
88
+
80
89
  loop do
81
- say "Select organization for this cloud:"
82
- say_new_line
83
90
  say "existing organizations:"
84
91
 
85
92
  organizations.each_with_index do |organization, i|
86
93
  print_wrapped "#{i + 1}) #{organization.name}", :ident => 2
87
94
  end
88
- say_new_line
89
-
90
- print_wrapped "#{count + 1}) provide name for new organization", :ident => 2
91
95
 
92
- option_selected = ask("Option:")
93
- break if ('1'..(count + 1).to_s).include?(option_selected)
94
- end
95
-
96
- if option_selected.to_i == count + 1
97
- return ask_for_new_organization(options)
98
- end
96
+ say green "Or leave empty to create a new organization"
97
+ say_new_line
99
98
 
100
- if (1..count).include?(option_selected.to_i)
101
- return organizations[option_selected.to_i - 1].name
99
+ selected = ask("Organization:")
100
+ if organizations.select { |o| o.name == selected }.present?
101
+ return selected
102
+ elsif selected.empty?
103
+ say_new_line
104
+ return ask_for_new_organization(options)
105
+ else
106
+ say_new_line
107
+ say_warning "#{selected} organization does not exist"
108
+ end
102
109
  end
103
110
  end
104
111
  end
@@ -113,6 +120,28 @@ module Shelly
113
120
  end
114
121
  end
115
122
 
123
+ def ask_for_region
124
+ regions = Shelly::App::REGIONS
125
+ say "Select region for this cloud:"
126
+ say_new_line
127
+
128
+ loop do
129
+ say "available regions:"
130
+
131
+ regions.each_with_index do |region, i|
132
+ print_wrapped "#{i + 1}) #{region}", :ident => 2
133
+ end
134
+ say_new_line
135
+
136
+ selected = ask("Region:").upcase
137
+ if regions.include?(selected)
138
+ return selected
139
+ else
140
+ say_new_line
141
+ say_warning "#{selected} region is not available"
142
+ end
143
+ end
144
+ end
116
145
  end
117
146
  end
118
147
  end
@@ -21,10 +21,10 @@ module Shelly
21
21
  say_new_line
22
22
 
23
23
  maintenances.each do |maintenance|
24
- started_at = Time.parse(maintenance['created_at']).
24
+ started_at = Time.parse(maintenance['created_at']).getlocal.
25
25
  strftime('%Y-%m-%d %H:%M:%S')
26
26
  finished_at = if maintenance['finished']
27
- Time.parse(maintenance['updated_at']).
27
+ Time.parse(maintenance['updated_at']).getlocal.
28
28
  strftime('%Y-%m-%d %H:%M:%S')
29
29
  else
30
30
  'in progress'
@@ -1,9 +1,10 @@
1
1
  class Shelly::Client
2
2
  def create_app(attributes)
3
3
  organization = attributes.delete(:organization_name)
4
+ region = attributes.delete(:region)
4
5
  zone = attributes.delete(:zone)
5
6
  post("/apps", :app => attributes, :organization_name => organization,
6
- :zone => zone)
7
+ :region => region, :zone => zone)
7
8
  end
8
9
 
9
10
  def delete_app(code_name)
@@ -1,3 +1,3 @@
1
1
  module Shelly
2
- VERSION = "0.4.42"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -153,6 +153,7 @@ describe Shelly::App do
153
153
  describe "#attributes" do
154
154
  before do
155
155
  @response = {"web_server_ip" => "192.0.2.1",
156
+ "region" => "EU",
156
157
  "state" => "running",
157
158
  "maintenance" => false,
158
159
  "organization" => {
@@ -190,6 +191,12 @@ describe Shelly::App do
190
191
  end
191
192
  end
192
193
 
194
+ describe "#region" do
195
+ it "should return cloud region" do
196
+ @app.region.should == "EU"
197
+ end
198
+ end
199
+
193
200
  describe "#state" do
194
201
  it "should return state of cloud" do
195
202
  @app.state.should == "running"
@@ -356,7 +363,8 @@ describe Shelly::App do
356
363
  attributes = {
357
364
  :code_name => "fooo",
358
365
  :organization_name => nil,
359
- :zone => nil
366
+ :zone => nil,
367
+ :region => nil
360
368
  }
361
369
  @client.should_receive(:create_app).with(attributes).and_return("git_url" => "git@git.shellycloud.com:fooo.git",
362
370
  "domains" => %w(fooo.shellyapp.com))
@@ -122,7 +122,7 @@ describe Shelly::CLI::Config do
122
122
  it "should warn that config file already exists in specified path" do
123
123
  Shelly::App.stub(:new).and_return(@app)
124
124
  @app.stub(:config_exists? => true)
125
- $stdout.should_receive(:puts).with(red "File 'new_config' already exists. Use `shelly config edit new_config --cloud ` to update it.")
125
+ $stdout.should_receive(:puts).with(red "File 'new_config' already exists. Use `shelly config edit new_config --cloud foo-production` to update it.")
126
126
  invoke(@config, :create, "new_config")
127
127
  end
128
128
 
@@ -29,31 +29,6 @@ describe Shelly::CLI::Endpoint do
29
29
  invoke(@cli, :list)
30
30
  end
31
31
 
32
- def endpoints_response
33
- [
34
- {'ip_address' => '10.0.0.1',
35
- 'sni' => true,
36
- 'uuid' => 'uuid1', 'info' => {
37
- 'domain' => 'example.com',
38
- 'issuer' => 'CA',
39
- 'subjcet' => 'organization info',
40
- 'since' => '2012-06-11 23:00:00 UTC',
41
- 'to' => '2015-06-11 23:00:00 UTC'
42
- }
43
- },
44
- {'ip_address' => '10.0.0.2',
45
- 'sni' => false,
46
- 'uuid' => 'uuid2', 'info' => {
47
- 'domain' => nil,
48
- 'issuer' => nil,
49
- 'subjcet' => nil,
50
- 'since' => nil,
51
- 'to' => nil
52
- }
53
- }
54
- ]
55
- end
56
-
57
32
  context "no endpoints" do
58
33
  it "should display information" do
59
34
  @app.should_receive(:endpoints).and_return([])
@@ -98,28 +73,86 @@ describe Shelly::CLI::Endpoint do
98
73
  File.stub(:read).with('crt_path').and_return('crt')
99
74
  File.stub(:read).with('key_path').and_return('key')
100
75
  File.stub(:read).with('bundle_path').and_return('bundle')
76
+ @app.stub(:endpoints).and_return([])
101
77
  end
102
78
 
103
- it "should create endpoint" do
79
+ it "should create endpoint with provided certificate" do
104
80
  @app.should_receive(:create_endpoint).with("crt\n", "key", true).
105
81
  and_return(endpoint_response('ip_address' => '10.0.0.1'))
106
82
 
83
+ $stdout.should_receive(:puts).with("Every unique IP address assigned to endpoint costs 10\u20AC/month")
84
+ $stdout.should_receive(:puts).with("It's required for SSL/TLS")
85
+ $stdout.should_receive(:print).with("Are you sure you want to create endpoint? (yes/no): ")
86
+
107
87
  $stdout.should_receive(:puts).with(green "Endpoint was created for #{@app.to_s} cloud")
108
88
  $stdout.should_receive(:puts).with("Deployed certificate on front end servers.")
109
89
  $stdout.should_receive(:puts).with("Point your domain to private IP address: 10.0.0.1")
110
90
 
111
91
  @cli.options = {"sni" => true}
112
- invoke(@cli, :create, "crt_path", "key_path")
92
+ fake_stdin(["yes"]) do
93
+ invoke(@cli, :create, "crt_path", "key_path")
94
+ end
95
+ end
96
+
97
+ context "without certificate" do
98
+ it "should create endpoint" do
99
+ @app.should_receive(:create_endpoint).with(nil, nil, true).
100
+ and_return(endpoint_response('ip_address' => '10.0.0.1'))
101
+
102
+ $stdout.should_receive(:puts).with("Every unique IP address assigned to endpoint costs 10\u20AC/month")
103
+ $stdout.should_receive(:puts).with("It's required for SSL/TLS")
104
+ $stdout.should_receive(:puts).with("You didn't provide certificate but it can be added later")
105
+ $stdout.should_receive(:puts).with("Assigned IP address can be used to catch all domains pointing to that address, without SSL/TLS enabled")
106
+ $stdout.should_receive(:print).with("Are you sure you want to create endpoint without certificate (yes/no): ")
107
+ $stdout.should_receive(:puts).with(green "Endpoint was created for #{@app.to_s} cloud")
108
+ $stdout.should_receive(:puts).with("Point your domain to private IP address: 10.0.0.1")
109
+
110
+ @cli.options = {"sni" => true}
111
+ fake_stdin(["yes"]) do
112
+ invoke(@cli, :create)
113
+ end
114
+ end
115
+ end
116
+
117
+ context "multiple endpoints" do
118
+ it "should create endpoint with provided certificate" do
119
+ @app.should_receive(:create_endpoint).with("crt\n", "key", nil).
120
+ and_return(endpoint_response('ip_address' => '10.0.0.1'))
121
+ @app.stub(:endpoints).and_return(endpoints_response)
122
+
123
+ $stdout.should_receive(:puts).with("Every unique IP address assigned to endpoint costs 10\u20AC/month")
124
+ $stdout.should_receive(:puts).with("It's required for SSL/TLS")
125
+ $stdout.should_receive(:puts).with(green "Available HTTP endpoints")
126
+ $stdout.should_receive(:puts).with("\n")
127
+ $stdout.should_receive(:puts).with(" UUID | IP address | Certificate | SNI")
128
+ $stdout.should_receive(:puts).with(" uuid1 | 10.0.0.1 | example.com | \u2713")
129
+ $stdout.should_receive(:puts).with(" uuid2 | 10.0.0.2 | \u2717 | \u2717")
130
+ $stdout.should_receive(:puts).with("\n")
131
+ $stdout.should_receive(:print).with("You already have assigned endpoint(s). Are you sure you want to create another one with a new IP address? (yes/no): ")
132
+ $stdout.should_receive(:puts).with(green "Endpoint was created for #{@app.to_s} cloud")
133
+ $stdout.should_receive(:puts).with("Deployed certificate on front end servers.")
134
+ $stdout.should_receive(:puts).with("Point your domain to private IP address: 10.0.0.1")
135
+
136
+ fake_stdin(["yes"]) do
137
+ invoke(@cli, :create, "crt_path", "key_path")
138
+ end
139
+ end
113
140
  end
114
141
 
115
142
  context "validation errors" do
116
143
  it "should show errors and exit" do
117
144
  exception = Shelly::Client::ValidationException.new({"errors" => [["key", "is invalid"]]})
118
145
  @app.should_receive(:create_endpoint).and_raise(exception)
146
+
147
+ $stdout.should_receive(:puts).with("Every unique IP address assigned to endpoint costs 10\u20AC/month")
148
+ $stdout.should_receive(:puts).with("It's required for SSL/TLS")
149
+ $stdout.should_receive(:print).with("Are you sure you want to create endpoint? (yes/no): ")
119
150
  $stdout.should_receive(:puts).with(red "Key is invalid")
120
151
 
121
152
  lambda {
122
- invoke(@cli, :create, "crt_path", "key_path", "bundle_path")
153
+ fake_stdin(["yes"]) do
154
+ invoke(@cli, :create, "crt_path", "key_path", "bundle_path")
155
+ end
123
156
  }.should raise_error(SystemExit)
124
157
  end
125
158
  end
@@ -127,10 +160,35 @@ describe Shelly::CLI::Endpoint do
127
160
  context "providing one only part of certificate" do
128
161
  it "should show error and exit" do
129
162
  @app.should_not_receive(:create_endpoint)
163
+
164
+ $stdout.should_receive(:puts).with("Every unique IP address assigned to endpoint costs 10\u20AC/month")
165
+ $stdout.should_receive(:puts).with("It's required for SSL/TLS")
166
+ $stdout.should_receive(:print).with("Are you sure you want to create endpoint? (yes/no): ")
130
167
  $stdout.should_receive(:puts).with(red "Provide both certificate and key")
131
168
 
132
169
  lambda {
133
- invoke(@cli, :create, "crt_path")
170
+ fake_stdin(["yes"]) do
171
+ invoke(@cli, :create, "crt_path")
172
+ end
173
+ }.should raise_error(SystemExit)
174
+ end
175
+ end
176
+
177
+ context "conflict error" do
178
+ it "should show errors and exit" do
179
+ exception = Shelly::Client::ConflictException.new("message" =>
180
+ "That's an error")
181
+ @app.should_receive(:create_endpoint).and_raise(exception)
182
+
183
+ $stdout.should_receive(:puts).with("Every unique IP address assigned to endpoint costs 10\u20AC/month")
184
+ $stdout.should_receive(:puts).with("It's required for SSL/TLS")
185
+ $stdout.should_receive(:print).with("Are you sure you want to create endpoint? (yes/no): ")
186
+ $stdout.should_receive(:puts).with(red "That's an error")
187
+
188
+ lambda {
189
+ fake_stdin(["yes"]) do
190
+ invoke(@cli, :create, "crt_path", "key_path", "bundle_path")
191
+ end
134
192
  }.should raise_error(SystemExit)
135
193
  end
136
194
  end
@@ -164,6 +222,19 @@ describe Shelly::CLI::Endpoint do
164
222
  }.should raise_error(SystemExit)
165
223
  end
166
224
  end
225
+
226
+ context "conflict error" do
227
+ it "should show errors and exit" do
228
+ exception = Shelly::Client::ConflictException.new("message" =>
229
+ "That's an error")
230
+ @app.should_receive(:update_endpoint).and_raise(exception)
231
+ $stdout.should_receive(:puts).with(red "That's an error")
232
+
233
+ lambda {
234
+ invoke(@cli, :update, "crt_path", "key_path", "bundle_path")
235
+ }.should raise_error(SystemExit)
236
+ end
237
+ end
167
238
  end
168
239
 
169
240
  describe "#delete" do
@@ -183,6 +254,31 @@ describe Shelly::CLI::Endpoint do
183
254
  end
184
255
  end
185
256
 
257
+ def endpoints_response
258
+ [
259
+ { 'ip_address' => '10.0.0.1',
260
+ 'sni' => true,
261
+ 'uuid' => 'uuid1', 'info' => {
262
+ 'domain' => 'example.com',
263
+ 'issuer' => 'CA',
264
+ 'subjcet' => 'organization info',
265
+ 'since' => '2012-06-11 23:00:00 UTC',
266
+ 'to' => '2015-06-11 23:00:00 UTC'
267
+ }
268
+ },
269
+ { 'ip_address' => '10.0.0.2',
270
+ 'sni' => false,
271
+ 'uuid' => 'uuid2', 'info' => {
272
+ 'domain' => nil,
273
+ 'issuer' => nil,
274
+ 'subjcet' => nil,
275
+ 'since' => nil,
276
+ 'to' => nil
277
+ }
278
+ }
279
+ ]
280
+ end
281
+
186
282
  def endpoint_response(options = {})
187
283
  {'ip_address' => '10.0.0.1', 'sni' => true,
188
284
  'uuid' => 'uuid1', 'info' => {
@@ -317,6 +317,7 @@ describe Shelly::CLI::Main do
317
317
  @app.stub(:git_remote_exist?).and_return(false)
318
318
  @main.stub(:check => true)
319
319
  @main.stub(:ask_for_organization)
320
+ @main.stub(:ask_for_region).and_return('EU')
320
321
  end
321
322
 
322
323
  # This spec tests inside_git_repository? hook
@@ -370,9 +371,29 @@ More info at http://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository\e[0m
370
371
  invoke(@main, :add)
371
372
  end
372
373
 
373
- it "should use zone from option" do
374
- @app.should_receive(:zone=).with('eu1')
375
- @main.options = {"zone" => "eu1"}
374
+ context "for zone param" do
375
+ it "should use zone from option" do
376
+ @app.should_receive(:zone=).with('zone')
377
+ @main.options = {"zone" => "zone"}
378
+ fake_stdin(["mycodename", ""]) do
379
+ invoke(@main, :add)
380
+ end
381
+ end
382
+
383
+ it "should not ask about the region" do
384
+ @app.should_not_receive(:region=)
385
+ $stdout.should_not_receive(:puts).
386
+ with("Select region for this cloud:")
387
+ @main.options = {"zone" => "zone"}
388
+ fake_stdin(["mycodename", ""]) do
389
+ invoke(@main, :add)
390
+ end
391
+ end
392
+ end
393
+
394
+ it "should use region from option" do
395
+ @app.should_receive(:region=).with('eu1')
396
+ @main.options = {"region" => "eu1"}
376
397
  fake_stdin(["mycodename", ""]) do
377
398
  invoke(@main, :add)
378
399
  end
@@ -476,7 +497,7 @@ More info at http://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository\e[0m
476
497
  @app.should_receive(:create).and_raise(exception)
477
498
  $stdout.should_receive(:puts).with(red "Code name has been already taken")
478
499
  $stdout.should_receive(:puts).with(red "Fix erros in the below command and type it again to create your cloud")
479
- $stdout.should_receive(:puts).with(red "shelly add --code-name=big-letters --databases=postgresql --organization=org-name --size=small")
500
+ $stdout.should_receive(:puts).with(red "shelly add --code-name=big-letters --databases=postgresql --organization=org-name --size=small --region=EU")
480
501
  lambda {
481
502
  fake_stdin(["BiG_LETTERS", ""]) do
482
503
  invoke(@main, :add)
@@ -608,7 +629,7 @@ More info at http://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository\e[0m
608
629
  it "should use --organization option" do
609
630
  @main.options = {"organization" => "foo"}
610
631
  @app.should_receive(:organization_name=).with("foo")
611
- fake_stdin(["foooo", "none"]) do
632
+ fake_stdin(["foo", "none"]) do
612
633
  invoke(@main, :add)
613
634
  end
614
635
  end
@@ -618,46 +639,51 @@ More info at http://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository\e[0m
618
639
  @client.stub(:organizations).and_return([{"name" => "aaa"}])
619
640
  end
620
641
 
621
- it "should ask user to choose organization if present and use chosen organization" do
622
- @app.should_receive(:organization_name=).with("aaa")
623
- $stdout.should_receive(:puts).with("Select organization for this cloud:")
642
+ it "should ask user to choose organization" do
643
+ $stdout.should_receive(:puts).
644
+ with("Select organization for this cloud:")
624
645
  $stdout.should_receive(:puts).with("existing organizations:")
625
646
  $stdout.should_receive(:puts).with(" 1) aaa")
626
- $stdout.should_receive(:puts).with(" 2) provide name for new organization")
627
- $stdout.should_receive(:print).with("Option: ")
628
- fake_stdin(["foooo", "none", "1"]) do
647
+ $stdout.should_receive(:puts).
648
+ with(green "Or leave empty to create a new organization")
649
+ $stdout.should_receive(:print).with("Organization: ")
650
+ fake_stdin(["foo", "none", "aaa"]) do
629
651
  invoke(@main, :add)
630
652
  end
631
653
  end
632
654
 
633
- it "should ask user to create new organization" do
634
- @main.options = {'redeem-code' => 'discount'}
635
- @client.should_receive(:create_organization).
636
- with({:name => "org-name", :redeem_code => 'discount'})
637
- @app.should_receive(:organization_name=).with('org-name')
638
- $stdout.should_receive(:puts).with("Select organization for this cloud:")
639
- $stdout.should_receive(:puts).with("existing organizations:")
640
- $stdout.should_receive(:puts).with(" 1) aaa")
641
- $stdout.should_receive(:puts).with(" 2) provide name for new organization")
642
- $stdout.should_receive(:print).with("Option: ")
643
- $stdout.should_receive(:print).with("Organization name (foo - default): ")
644
- $stdout.should_receive(:puts).with(green "Organization 'org-name' created")
645
- fake_stdin(["foooo", "none", "2", "org-name"]) do
655
+ it "should keep asking until user will provide a valid option" do
656
+ $stdout.should_receive(:print).with("Organization: ").twice
657
+ fake_stdin(["foo", "none", "bbb", "aaa"]) do
658
+ invoke(@main, :add)
659
+ end
660
+ end
661
+
662
+ it "should use choosen organization" do
663
+ @app.should_receive(:organization_name=).with("aaa")
664
+ fake_stdin(["foo", "none", "aaa"]) do
646
665
  invoke(@main, :add)
647
666
  end
648
667
  end
649
668
 
650
- it "should use redeem-code option" do
669
+ it "should ask user to create a new organization" do
670
+ @app.should_receive(:organization_name=).with('org-name')
651
671
  @client.should_receive(:create_organization).
652
672
  with({:name => "org-name", :redeem_code => nil})
653
- $stdout.should_receive(:puts).with("Select organization for this cloud:")
654
- $stdout.should_receive(:puts).with("existing organizations:")
655
- $stdout.should_receive(:puts).with(" 1) aaa")
656
- $stdout.should_receive(:puts).with(" 2) provide name for new organization")
657
- $stdout.should_receive(:print).with("Option: ")
658
- $stdout.should_receive(:print).with("Organization name (foo - default): ")
659
- $stdout.should_receive(:puts).with(green "Organization 'org-name' created")
660
- fake_stdin(["foooo", "none", "2", "org-name"]) do
673
+ $stdout.should_receive(:print).
674
+ with("Organization name (foo - default): ")
675
+ $stdout.should_receive(:puts).
676
+ with(green "Organization 'org-name' created")
677
+ fake_stdin(["foo", "none", "", "org-name"]) do
678
+ invoke(@main, :add)
679
+ end
680
+ end
681
+
682
+ it "should use --redeem-code option" do
683
+ @main.options = {'redeem-code' => 'discount'}
684
+ @client.should_receive(:create_organization).
685
+ with({:name => "org-name", :redeem_code => 'discount'})
686
+ fake_stdin(["foo", "none", "", "org-name"]) do
661
687
  invoke(@main, :add)
662
688
  end
663
689
  end
@@ -668,8 +694,11 @@ More info at http://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository\e[0m
668
694
  response = {"resource" => "organization"}
669
695
  exception = Shelly::Client::NotFoundException.new(response)
670
696
  @app.should_receive(:create).and_raise(exception)
671
- $stdout.should_receive(:puts).with(red "Organization 'foo' not found")
672
- $stdout.should_receive(:puts).with(red "You can list organizations you have access to with `shelly organization list`")
697
+ $stdout.should_receive(:puts).
698
+ with(red "Organization 'foo' not found")
699
+ $stdout.should_receive(:puts).
700
+ with(red "You can list organizations you have access to with" \
701
+ " `shelly organization list`")
673
702
 
674
703
  expect do
675
704
  fake_stdin(["foooo", "none"]) do
@@ -678,6 +707,59 @@ More info at http://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository\e[0m
678
707
  end.to raise_error(SystemExit)
679
708
  end
680
709
  end
710
+
711
+ context "for region" do
712
+ before do
713
+ @main.unstub(:ask_for_region)
714
+ end
715
+
716
+ it "should use the value from the --region option" do
717
+ @main.options = {"region" => "EU"}
718
+ @app.should_receive(:region=).with("EU")
719
+ fake_stdin(["foo", "none"]) do
720
+ invoke(@main, :add)
721
+ end
722
+ end
723
+
724
+ it "should ask user to choose the region" do
725
+ @app.should_receive(:region=).with("NA")
726
+ $stdout.should_receive(:puts).with("Select region for this cloud:")
727
+ $stdout.should_receive(:puts).with("available regions:")
728
+ $stdout.should_receive(:puts).with(" 1) EU")
729
+ $stdout.should_receive(:puts).with(" 2) NA")
730
+ $stdout.should_receive(:print).with("Region: ")
731
+ fake_stdin(["foo", "none", "NA"]) do
732
+ invoke(@main, :add)
733
+ end
734
+ end
735
+
736
+ context "when given region is not available" do
737
+ it "should print a warning message and ask again" do
738
+ $stdout.should_receive(:puts).
739
+ with(yellow "ASIA region is not available")
740
+ $stdout.should_receive(:puts).with("available regions:").twice
741
+ fake_stdin(["foo", "none", "ASIA", "NA"]) do
742
+ invoke(@main, :add)
743
+ end
744
+ end
745
+ end
746
+
747
+ context "when given region does not accepts new apps" do
748
+ it "should show that it is not available" do
749
+ @main.options = {"region" => "NA"}
750
+ response = {"error" => "Given region is unavailable"}
751
+ exception = Shelly::Client::ConflictException.new(response)
752
+ @app.should_receive(:create).and_raise(exception)
753
+ $stdout.should_receive(:puts).with(red "Given region is unavailable")
754
+
755
+ expect do
756
+ fake_stdin(["foo", "none", "NA"]) do
757
+ invoke(@main, :add)
758
+ end
759
+ end.to raise_error(SystemExit)
760
+ end
761
+ end
762
+ end
681
763
  end
682
764
 
683
765
  describe "#list" do
@@ -1006,6 +1088,7 @@ Wait until cloud is in 'turned off' state and try again.")
1006
1088
  it "should display basic information about cloud" do
1007
1089
  @main.should_receive(:multiple_clouds).and_return(@app)
1008
1090
  $stdout.should_receive(:puts).with(green "Cloud foo-production:")
1091
+ $stdout.should_receive(:puts).with(" Region: EU")
1009
1092
  $stdout.should_receive(:puts).with(" State: running")
1010
1093
  $stdout.should_receive(:puts).with(" Deployed commit sha: 52e65ed2d085eaae560cdb81b2b56a7d76")
1011
1094
  $stdout.should_receive(:puts).with(" Deployed commit message: Commit message")
@@ -1068,6 +1151,7 @@ Wait until cloud is in 'turned off' state and try again.")
1068
1151
  "maintenance" => true}))
1069
1152
  @main.should_receive(:multiple_clouds).and_return(@app)
1070
1153
  $stdout.should_receive(:puts).with(red "Cloud foo-production:")
1154
+ $stdout.should_receive(:puts).with(" Region: EU")
1071
1155
  $stdout.should_receive(:puts).with(" State: admin maintenance in progress")
1072
1156
  $stdout.should_receive(:puts).with(" Deployed commit sha: 52e65ed2d085eaae560cdb81b2b56a7d76")
1073
1157
  $stdout.should_receive(:puts).with(" Deployed commit message: Commit message")
@@ -1101,6 +1185,7 @@ Wait until cloud is in 'turned off' state and try again.")
1101
1185
  "maintenance" => false}))
1102
1186
  @main.should_receive(:multiple_clouds).and_return(@app)
1103
1187
  $stdout.should_receive(:puts).with(red "Cloud foo-production:")
1188
+ $stdout.should_receive(:puts).with(" Region: EU")
1104
1189
  $stdout.should_receive(:puts).with(" State: running (last deployment failed) (deployment log: `shelly deploys show last -c foo-production`)")
1105
1190
  $stdout.should_receive(:puts).with(" Deployed commit sha: 52e65ed2d085eaae560cdb81b2b56a7d76")
1106
1191
  $stdout.should_receive(:puts).with(" Deployed commit message: Commit message")
@@ -1148,6 +1233,7 @@ Wait until cloud is in 'turned off' state and try again.")
1148
1233
 
1149
1234
  def response(options = {})
1150
1235
  { "code_name" => "foo-production",
1236
+ "region" => "EU",
1151
1237
  "state" => "running",
1152
1238
  "state_description" => "running",
1153
1239
  "git_info" => {
@@ -171,9 +171,10 @@ describe Shelly::Client do
171
171
  describe "#create_app" do
172
172
  it "should send post with app's attributes" do
173
173
  @client.should_receive(:post).with("/apps", :app => {:code_name => "foo",
174
- :ruby_version => "1.9.2"}, :organization_name => "foo", :zone => 'eu1')
174
+ :ruby_version => "1.9.2"}, :organization_name => "foo", :region => 'EU',
175
+ :zone => nil)
175
176
  @client.create_app(:code_name => "foo", :ruby_version => "1.9.2",
176
- :organization_name => "foo", :zone => "eu1")
177
+ :organization_name => "foo", :region => "EU", :zone => nil)
177
178
  end
178
179
  end
179
180
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shelly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.42
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shelly Cloud team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-14 00:00:00.000000000 Z
11
+ date: 2015-01-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec