shelly 0.4.38 → 0.4.39

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a378b3163f2759b50c3527162a36a2e448aaa0a2
4
- data.tar.gz: e51cc9e70dc529e7ebf7e1b638dd7972afc4a94c
3
+ metadata.gz: b5d9e5112799516f4300810c0c9d4bc63a755a18
4
+ data.tar.gz: ef02f4bd1ef58a34a5c72a566e22d99a685938dc
5
5
  SHA512:
6
- metadata.gz: 65b56e13341eb0e9ae7a8ed219c9537ab43d96c78b9c7e98ac9cb1f6c1d1d38752cc7f843b3105bbd30a5212aa95d236e97706be858c4af4ae0d23e577aeb0db
7
- data.tar.gz: 605a7ea1cd53db41017d14f98432c793ac332983911425b325fed46885ebe8029860523070f487c40f61c84b480f68ccca80f18d3d52a17ac165b73ce6a0c43a
6
+ metadata.gz: 3eaac18b74f4977637ff4d26d0d019ba4f3288a469caaa819fde9b90190c850198ec184ca0e4bf67c25d9bb7bc65ca105fd4e9c4e446bcd72cd5bc22c0f953de
7
+ data.tar.gz: 8fa35d39646836f2405484650bbba28b26b8f836349d7ff9e0e68e5c5b58b12a7cc4e3bab8e0c1cfe64554f6306f0e900f43efca319319ef6a2f803d63e43d6a
@@ -1,9 +1,9 @@
1
1
  rvm:
2
- - "2.1"
3
- - 2.0.0
4
- - 1.9.3
5
- - jruby-19mode
2
+ - '2.1'
3
+ - 2.0.0
4
+ - 1.9.3
5
+ - jruby-19mode
6
6
  notifications:
7
7
  email: false
8
- campfire:
9
- secure: 'ZSIx+w/r0QrOtpWu8EfmlypA9+pCRYSNU01Hv0ZvxOBu1EEp1Z/sDif0dCyyLrhv7lUOESdlcfmwVXUx93zEk2f+YMakG0NBnvMUhlkUhBLEsxDdPIgihhTirUIcWLrtPhtUbFA68/eXAP55wlz4Vcou5CHz8kk0+qmUX7QnqlI='
8
+ slack:
9
+ secure: D5ohRHtjO58jbSOGxZIGFIBQ0GLGhpgojxgrNFxwebzyvfN4kQK9iDdurWapwuXPpsDukLz8gnnlaboJ0wjmqjp4MEtXoAO+3PdYHChPOiL/bSpOAtuE5o/Gh2LVu6RXI+//cuxjfREE2bSbdFJnFzlb3lccuoU4x1c3JB5YbS4=
@@ -1,3 +1,8 @@
1
+ ## 0.4.39 / 2014-11-17
2
+
3
+ * [improvement] API changed to support multiple certificates and IP addresses,
4
+ resource name changed from Cert to Endpoint
5
+
1
6
  ## 0.4.38 / 2014-10-20
2
7
 
3
8
  * [improvement] Deployment logs procesess moved after puma
@@ -215,16 +215,24 @@ module Shelly
215
215
  configs.any? { |config| config["path"] == path }
216
216
  end
217
217
 
218
- def cert
219
- shelly.cert(code_name)
218
+ def endpoints
219
+ shelly.endpoints(code_name)
220
220
  end
221
221
 
222
- def create_cert(content, key)
223
- shelly.create_cert(code_name, content, key)
222
+ def endpoint(uuid)
223
+ shelly.endpoint(code_name, uuid)
224
224
  end
225
225
 
226
- def update_cert(content, key)
227
- shelly.update_cert(code_name, content, key)
226
+ def create_endpoint(certificate, key, sni)
227
+ shelly.create_endpoint(code_name, certificate, key, sni)
228
+ end
229
+
230
+ def update_endpoint(uuid, certificate, key)
231
+ shelly.update_endpoint(code_name, uuid, certificate, key)
232
+ end
233
+
234
+ def delete_endpoint(uuid)
235
+ shelly.delete_endpoint(code_name, uuid)
228
236
  end
229
237
 
230
238
  def rake(task)
@@ -87,7 +87,7 @@ module Shelly
87
87
  def restore(filename)
88
88
  app = multiple_clouds(options[:cloud], "backup restore FILENAME")
89
89
  backup = app.database_backup(filename)
90
- say "You are about restore #{backup.kind} database for cloud #{backup.code_name} to state from #{backup.filename}"
90
+ say "You are about to restore #{backup.kind} database for cloud #{backup.code_name} to state from #{backup.filename}"
91
91
  say_new_line
92
92
  ask_to_restore_database
93
93
  app.restore_backup(filename)
@@ -0,0 +1,175 @@
1
+ # encoding: utf-8
2
+
3
+ require "shelly/cli/command"
4
+
5
+ module Shelly
6
+ module CLI
7
+ class Endpoint < Command
8
+ namespace :endpoint
9
+ include Helpers
10
+
11
+ before_hook :logged_in?, :only => [:index, :show, :create, :update]
12
+
13
+ class_option :cloud, :type => :string, :aliases => "-c", :desc => "Specify cloud"
14
+
15
+ desc "list", "List HTTP endpoints"
16
+ def list
17
+ app = multiple_clouds(options[:cloud], "endpoint list")
18
+
19
+ endpoints = app.endpoints
20
+
21
+ if endpoints.present?
22
+ say "Available HTTP endpoints", :green
23
+ say_new_line
24
+ to_display = [["UUID", "| IP address", "| Certificate", "| SNI"]]
25
+
26
+ endpoints.each do |endpoint|
27
+
28
+ to_display << [
29
+ endpoint['uuid'],
30
+ "| #{print_check(endpoint['ip_address'], :return_value => true)}",
31
+ "| #{print_check(endpoint['info']['domain'], :return_value => true)}",
32
+ "| #{print_check(endpoint['sni'])}"
33
+ ]
34
+ end
35
+
36
+ print_table(to_display, :ident => 2)
37
+
38
+ else
39
+ say "No HTTP endpoints available"
40
+ end
41
+ end
42
+
43
+ desc "show", "Show detail information about HTTP endpoint"
44
+ def show(uuid)
45
+ app = multiple_clouds(options[:cloud], "endpoint show UUID")
46
+
47
+ endpoint = app.endpoint(uuid)
48
+
49
+ say "UUID: #{endpoint['uuid']}"
50
+ say "IP address: #{endpoint['ip_address']}", nil, true
51
+ say "SNI: #{"✓" if endpoint['sni']}", nil, true
52
+
53
+ say_new_line
54
+ if endpoint['info']['subject'] && endpoint['info']['issuer']
55
+ say "Certificate details:", :green
56
+ say "Domain: #{endpoint['info']['domain']}", nil, true
57
+ say "Issuer: #{endpoint['info']['issuer']}"
58
+ say "Subject: #{endpoint['info']['subject']}"
59
+ say "Not valid before: #{Time.parse(endpoint['info']['since']).
60
+ getlocal.strftime("%Y-%m-%d %H:%M:%S")}"
61
+ say "Expires: #{Time.parse(endpoint['info']['to']).
62
+ getlocal.strftime("%Y-%m-%d %H:%M:%S")}"
63
+ else
64
+ say "No SSL certificate added"
65
+ end
66
+ rescue Client::NotFoundException => e
67
+ raise unless e.resource == :endpoint
68
+ say_error "Endpoint not found"
69
+ end
70
+
71
+ desc "create [CERT_PATH] [KEY_PATH] [BUNDLE_PATH]", "Add HTTP endpoint " \
72
+ "to your cloud"
73
+ long_desc %{
74
+ Add HTTP endpoint to your cloud. Adding SSL certificate is optional and not required\n
75
+ CERT_PATH - path to certificate.\n
76
+ KEY_PATH - path to private key.\n
77
+ BUNDLE_PATH - optional path to certificate bundle path.
78
+ }
79
+ method_option "sni", :type => :boolean,
80
+ :desc => "Create SNI endpoint"
81
+ def create(cert_path = nil, key_path = nil, bundle_path = nil)
82
+ app = multiple_clouds(options[:cloud],
83
+ "endpoint create [CERT_PATH] [KEY_PATH] [BUNDLE_PATH]")
84
+
85
+ certificate, key = read_certificate_components(cert_path, key_path,
86
+ bundle_path)
87
+
88
+ endpoint = app.create_endpoint(certificate, key, options["sni"])
89
+
90
+ say "Endpoint was created for #{app} cloud", :green
91
+ if endpoint['ip_address']
92
+ say "Deployed certificate on front end servers." if certificate && key
93
+ say "Point your domain to private IP address: #{endpoint['ip_address']}"
94
+ else
95
+ say "Private IP address was requested for your cloud."
96
+ say "Support has been notified and will contact you shortly."
97
+ end
98
+ rescue Client::ValidationException => e
99
+ e.each_error { |error| say_error error, :with_exit => false }
100
+ exit 1
101
+ end
102
+
103
+ desc "update UUID CERT_PATH KEY_PATH [BUNDLE_PATH]", "Update HTTP "\
104
+ "endpoint by adding SSL certificate"
105
+ long_desc %{
106
+ Update current HTTP endpoint with SSL certificate\n
107
+ CERT_PATH - path to certificate.\n
108
+ KEY_PATH - path to private key.\n
109
+ BUNDLE_PATH - optional path to certificate bundle path.
110
+ }
111
+ def update(uuid, cert_path, key_path, bundle_path = nil)
112
+ app = multiple_clouds(options[:cloud],
113
+ "endpoint update UUID CERT_PATH KEY_PATH [BUNDLE_PATH]")
114
+
115
+ certificate, key = read_certificate_components(cert_path, key_path,
116
+ bundle_path)
117
+
118
+ endpoint = app.update_endpoint(uuid, certificate, key)
119
+
120
+ say "Endpoint was updated", :green
121
+ if endpoint['ip_address']
122
+ say "Deployed certificate on front end servers."
123
+ say "Point your domain to private IP address: #{endpoint['ip_address']}"
124
+ else
125
+ say "Private IP address was requested for your cloud."
126
+ say "Support has been notified and will contact you shortly."
127
+ end
128
+ rescue Client::ValidationException => e
129
+ e.each_error { |error| say_error error, :with_exit => false }
130
+ exit 1
131
+ rescue Client::NotFoundException => e
132
+ raise unless e.resource == :certificate
133
+ say_error "Endpoint not found"
134
+ end
135
+
136
+ desc "delete UUID", "Delete HTTP endpoint"
137
+ def delete(uuid)
138
+ app = multiple_clouds(options[:cloud], "endpoint delete UUID")
139
+ endpoint = app.endpoint(uuid)
140
+
141
+ if endpoint['ip_address']
142
+ say_warning "Removing endpoint will release #{endpoint['ip_address']} IP address."
143
+ end
144
+ if yes?("Are you sure you want to delete endpoint (yes/no):")
145
+ app.delete_endpoint(uuid)
146
+ say "Endpoint was deleted"
147
+ end
148
+ rescue Client::NotFoundException => e
149
+ raise unless e.resource == :certificate
150
+ say_error "Endpoint not found"
151
+ end
152
+
153
+ no_tasks do
154
+ def print_check(check, options = {})
155
+ return check if options[:return_value] && check
156
+ check ? "✓" : "✗"
157
+ end
158
+
159
+ def read_certificate_components(cert_path, key_path, bundle_path)
160
+ if cert_path || key_path
161
+ say_error "Provide both certificate and key" unless (cert_path && key_path)
162
+
163
+ certificate = ::File.read(cert_path).strip
164
+ bundle = bundle_path ? ::File.read(bundle_path).strip : ""
165
+ key = ::File.read(key_path).strip
166
+
167
+ certificate = certificate + "\n" + bundle
168
+
169
+ [certificate, key]
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end
@@ -7,7 +7,7 @@ require "shelly/cli/config"
7
7
  require "shelly/cli/file"
8
8
  require "shelly/cli/organization"
9
9
  require "shelly/cli/logs"
10
- require "shelly/cli/cert"
10
+ require "shelly/cli/endpoint"
11
11
  require "shelly/cli/maintenance"
12
12
 
13
13
  require "shelly/cli/main/add"
@@ -26,7 +26,7 @@ module Shelly
26
26
  register_subcommand(File, "file", "file <command>", "Upload and download files to and from persistent storage")
27
27
  register_subcommand(Organization, "organization", "organization <command>", "View organizations")
28
28
  register_subcommand(Logs, "log", "logs <command>", "View application logs")
29
- register_subcommand(Cert, "cert", "cert <command>", "Mange application certificates")
29
+ register_subcommand(Endpoint, "endpoint", "cert <command>", "Mange application HTTP(S) endpoints")
30
30
  register_subcommand(Maintenance, "maintenance", "maintenance <command>", "Mange application maintenance events")
31
31
 
32
32
  check_unknown_options!(:except => :rake)
@@ -118,7 +118,7 @@ module Shelly
118
118
  print_wrapped "Deployed by: #{app.git_info["deployed_push_author"]}", :ident => 2
119
119
  say_new_line
120
120
  print_wrapped "Repository URL: #{app.git_info["repository_url"]}", :ident => 2
121
- print_wrapped "Web server IP: #{app.web_server_ip}", :ident => 2
121
+ print_wrapped "Web server IP: #{app.web_server_ip.join(', ')}", :ident => 2
122
122
  say_new_line
123
123
 
124
124
  print_wrapped "Usage:", :ident => 2
@@ -18,7 +18,7 @@ module Shelly
18
18
  require 'shelly/client/ssh_keys'
19
19
  require 'shelly/client/organizations'
20
20
  require 'shelly/client/auth'
21
- require 'shelly/client/cert'
21
+ require 'shelly/client/endpoint'
22
22
  require 'shelly/client/maintenance'
23
23
 
24
24
  def api_url
@@ -0,0 +1,25 @@
1
+ class Shelly::Client
2
+ def endpoints(cloud)
3
+ get("/apps/#{cloud}/endpoints")
4
+ end
5
+
6
+ def endpoint(cloud, uuid)
7
+ get("/apps/#{cloud}/endpoints/#{uuid}")
8
+ end
9
+
10
+ def create_endpoint(cloud, certificate, key, sni)
11
+ endpoint = certificate && key ? {:certificate => certificate,
12
+ :key => key} : {}
13
+
14
+ post("/apps/#{cloud}/endpoints", :endpoint => endpoint.merge(:sni => sni))
15
+ end
16
+
17
+ def update_endpoint(cloud, uuid, certificate, key)
18
+ put("/apps/#{cloud}/endpoints/#{uuid}",
19
+ :endpoint => {:certificate => certificate, :key => key})
20
+ end
21
+
22
+ def delete_endpoint(cloud, uuid)
23
+ delete("/apps/#{cloud}/endpoints/#{uuid}")
24
+ end
25
+ end
@@ -1,3 +1,3 @@
1
1
  module Shelly
2
- VERSION = "0.4.38"
2
+ VERSION = "0.4.39"
3
3
  end
@@ -541,20 +541,39 @@ describe Shelly::App do
541
541
  end
542
542
  end
543
543
 
544
- context "certificate" do
545
- it "#show_cert should query api" do
546
- @client.should_receive(:cert).with(@app.code_name)
547
- @app.cert
544
+ describe "#endpoints" do
545
+ it "should use api" do
546
+ @client.should_receive(:endpoints).with(@app.code_name)
547
+ @app.endpoints
548
548
  end
549
+ end
550
+
551
+ describe "#show_endpoint" do
552
+ it "should use api" do
553
+ @client.should_receive(:endpoint).with(@app.code_name, 'uuid')
554
+ @app.endpoint('uuid')
555
+ end
556
+ end
549
557
 
550
- it "#create_cert should query api" do
551
- @client.should_receive(:create_cert).with(@app.code_name, 'crt', 'key')
552
- @app.create_cert("crt", "key")
558
+ describe "#create_cert" do
559
+ it "should use api" do
560
+ @client.should_receive(:create_endpoint).with(@app.code_name, 'crt', 'key', true)
561
+ @app.create_endpoint("crt", "key", true)
553
562
  end
563
+ end
564
+
565
+ describe "#update_cert" do
566
+ it "should use api" do
567
+ @client.should_receive(:update_endpoint).with(@app.code_name, 'uuid',
568
+ "crt", "key")
569
+ @app.update_endpoint("uuid", "crt", "key")
570
+ end
571
+ end
554
572
 
555
- it "#update_cert should query api" do
556
- @client.should_receive(:update_cert).with(@app.code_name, 'crt', 'key')
557
- @app.update_cert("crt", "key")
573
+ describe "#delete_endpoint" do
574
+ it "should use api" do
575
+ @client.should_receive(:delete_endpoint).with(@app.code_name, "uuid")
576
+ @app.delete_endpoint("uuid")
558
577
  end
559
578
  end
560
579
 
@@ -233,7 +233,7 @@ describe Shelly::CLI::Backup do
233
233
  end
234
234
 
235
235
  it "should restore database" do
236
- $stdout.should_receive(:puts).with("You are about restore postgresql database for cloud foo-staging to state from better.tar.gz")
236
+ $stdout.should_receive(:puts).with("You are about to restore postgresql database for cloud foo-staging to state from better.tar.gz")
237
237
  $stdout.should_receive(:print).with("I want to restore the database (yes/no): ")
238
238
  $stdout.should_receive(:puts).with("\n")
239
239
  @client.stub(:restore_backup).with("todo-list-test","better.tar.gz")
@@ -247,7 +247,7 @@ describe Shelly::CLI::Backup do
247
247
 
248
248
  context "when answering no" do
249
249
  it "should cancel restore database" do
250
- $stdout.should_receive(:puts).with("You are about restore postgresql database for cloud foo-staging to state from better.tar.gz")
250
+ $stdout.should_receive(:puts).with("You are about to restore postgresql database for cloud foo-staging to state from better.tar.gz")
251
251
  $stdout.should_receive(:print).with("I want to restore the database (yes/no): ")
252
252
  $stdout.should_receive(:puts).with("\n")
253
253
  $stdout.should_receive(:puts).with(red "Canceled")
@@ -0,0 +1,197 @@
1
+ require "spec_helper"
2
+ require "shelly/cli/endpoint"
3
+
4
+ describe Shelly::CLI::Endpoint do
5
+ before do
6
+ FileUtils.stub(:chmod)
7
+ @cli = Shelly::CLI::Endpoint.new
8
+ Shelly::CLI::Endpoint.stub(:new).and_return(@cli)
9
+ @client = mock
10
+ Shelly::Client.stub(:new).and_return(@client)
11
+ @client.stub(:authorize!)
12
+ FileUtils.mkdir_p("/projects/foo")
13
+ Dir.chdir("/projects/foo")
14
+ @app = Shelly::App.new("foo-production")
15
+ Shelly::App.stub(:new).and_return(@app)
16
+ File.open("Cloudfile", 'w') { |f| f.write("foo-production:\n") }
17
+ end
18
+
19
+ describe "#index" do
20
+ it "should show all endpoints" do
21
+ @app.should_receive(:endpoints).and_return(endpoints_response)
22
+
23
+ $stdout.should_receive(:puts).with(green "Available HTTP endpoints")
24
+ $stdout.should_receive(:puts).with("\n")
25
+ $stdout.should_receive(:puts).with(" UUID | IP address | Certificate | SNI")
26
+ $stdout.should_receive(:puts).with(" uuid1 | 10.0.0.1 | example.com | \u2713")
27
+ $stdout.should_receive(:puts).with(" uuid2 | 10.0.0.2 | \u2717 | \u2717")
28
+
29
+ invoke(@cli, :list)
30
+ end
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
+ context "no endpoints" do
58
+ it "should display information" do
59
+ @app.should_receive(:endpoints).and_return([])
60
+ $stdout.should_receive(:puts).with("No HTTP endpoints available")
61
+ invoke(@cli, :list)
62
+ end
63
+ end
64
+ end
65
+
66
+ describe "#show" do
67
+ it "should description" do
68
+ @app.should_receive(:endpoint).with('uuid1').and_return(endpoint_response)
69
+ $stdout.should_receive(:puts).with("UUID: uuid1")
70
+ $stdout.should_receive(:puts).with("IP address: 10.0.0.1")
71
+ $stdout.should_receive(:puts).with("SNI: \u2713")
72
+ $stdout.should_receive(:puts).with("\n")
73
+ $stdout.should_receive(:puts).with(green "Certificate details:")
74
+ $stdout.should_receive(:puts).with("Domain: example.com")
75
+ $stdout.should_receive(:puts).with("Issuer: CA")
76
+ $stdout.should_receive(:puts).with("Subject: organization info")
77
+ $stdout.should_receive(:puts).with("Not valid before:"\
78
+ " #{Time.parse(endpoint_response['info']['since']).getlocal.strftime("%Y-%m-%d %H:%M:%S")}")
79
+ $stdout.should_receive(:puts).with("Expires:"\
80
+ " #{Time.parse(endpoint_response['info']['to']).getlocal.strftime("%Y-%m-%d %H:%M:%S")}")
81
+ invoke(@cli, :show, 'uuid1')
82
+ end
83
+
84
+ context "endpoint not found" do
85
+ it "should exit" do
86
+ exception = Shelly::Client::NotFoundException.new("resource" => "endpoint")
87
+ @app.should_receive(:endpoint).with('uuid').and_raise(exception)
88
+ $stdout.should_receive(:puts).with(red "Endpoint not found")
89
+ lambda {
90
+ invoke(@cli, :show, 'uuid')
91
+ }.should raise_error(SystemExit)
92
+ end
93
+ end
94
+ end
95
+
96
+ describe "#create" do
97
+ before do
98
+ File.stub(:read).with('crt_path').and_return('crt')
99
+ File.stub(:read).with('key_path').and_return('key')
100
+ File.stub(:read).with('bundle_path').and_return('bundle')
101
+ end
102
+
103
+ it "should create endpoint" do
104
+ @app.should_receive(:create_endpoint).with("crt\n", "key", true).
105
+ and_return(endpoint_response('ip_address' => '10.0.0.1'))
106
+
107
+ $stdout.should_receive(:puts).with(green "Endpoint was created for #{@app.to_s} cloud")
108
+ $stdout.should_receive(:puts).with("Deployed certificate on front end servers.")
109
+ $stdout.should_receive(:puts).with("Point your domain to private IP address: 10.0.0.1")
110
+
111
+ @cli.options = {"sni" => true}
112
+ invoke(@cli, :create, "crt_path", "key_path")
113
+ end
114
+
115
+ context "validation errors" do
116
+ it "should show errors and exit" do
117
+ exception = Shelly::Client::ValidationException.new({"errors" => [["key", "is invalid"]]})
118
+ @app.should_receive(:create_endpoint).and_raise(exception)
119
+ $stdout.should_receive(:puts).with(red "Key is invalid")
120
+
121
+ lambda {
122
+ invoke(@cli, :create, "crt_path", "key_path", "bundle_path")
123
+ }.should raise_error(SystemExit)
124
+ end
125
+ end
126
+
127
+ context "providing one only part of certificate" do
128
+ it "should show error and exit" do
129
+ @app.should_not_receive(:create_endpoint)
130
+ $stdout.should_receive(:puts).with(red "Provide both certificate and key")
131
+
132
+ lambda {
133
+ invoke(@cli, :create, "crt_path")
134
+ }.should raise_error(SystemExit)
135
+ end
136
+ end
137
+ end
138
+
139
+ describe "#update" do
140
+ before do
141
+ File.stub(:read).with('crt_path').and_return('crt')
142
+ File.stub(:read).with('key_path').and_return('key')
143
+ File.stub(:read).with('bundle_path').and_return('bundle')
144
+ end
145
+
146
+ it "should create endpoint" do
147
+ @app.should_receive(:update_endpoint).with('uuid', "crt\nbundle", "key").
148
+ and_return(endpoint_response)
149
+ $stdout.should_receive(:puts).with(green "Endpoint was updated")
150
+ $stdout.should_receive(:puts).with("Deployed certificate on front end servers.")
151
+ $stdout.should_receive(:puts).with("Point your domain to private IP address: 10.0.0.1")
152
+
153
+ invoke(@cli, :update, 'uuid', "crt_path", "key_path", "bundle_path")
154
+ end
155
+
156
+ context "validation errors" do
157
+ it "should show errors and exit" do
158
+ exception = Shelly::Client::ValidationException.new({"errors" => [["key", "is invalid"]]})
159
+ @app.should_receive(:update_endpoint).and_raise(exception)
160
+ $stdout.should_receive(:puts).with(red "Key is invalid")
161
+
162
+ lambda {
163
+ invoke(@cli, :update, 'uuid', "crt_path", "key_path", "bundle_path")
164
+ }.should raise_error(SystemExit)
165
+ end
166
+ end
167
+ end
168
+
169
+ describe "#delete" do
170
+ it "should ask to delete endpoint" do
171
+ @app.should_receive(:endpoint).with('uuid').
172
+ and_return(endpoint_response)
173
+ @app.should_receive(:delete_endpoint).with('uuid')
174
+
175
+ $stdout.should_receive(:puts).with(yellow "Removing endpoint will release 10.0.0.1 IP address.")
176
+ $stdout.should_receive(:print).with("Are you sure you want to delete endpoint (yes/no): ")
177
+ $stdout.should_receive(:puts).with("Endpoint was deleted")
178
+
179
+ fake_stdin(["yes"]) do
180
+ invoke(@cli, :delete, 'uuid')
181
+ end
182
+
183
+ end
184
+ end
185
+
186
+ def endpoint_response(options = {})
187
+ {'ip_address' => '10.0.0.1', 'sni' => true,
188
+ 'uuid' => 'uuid1', 'info' => {
189
+ 'domain' => 'example.com',
190
+ 'issuer' => 'CA',
191
+ 'subject' => 'organization info',
192
+ 'since' => '2012-06-11 23:00:00 UTC',
193
+ 'to' => '2015-06-11 23:00:00 UTC'
194
+ }
195
+ }.merge(options)
196
+ end
197
+ end
@@ -1176,7 +1176,7 @@ Wait until cloud is in 'turned off' state and try again.")
1176
1176
  }
1177
1177
  }
1178
1178
  },
1179
- "web_server_ip" => "22.22.22.22"}.merge(options)
1179
+ "web_server_ip" => ["22.22.22.22"]}.merge(options)
1180
1180
  end
1181
1181
  end
1182
1182
 
@@ -432,22 +432,32 @@ describe Shelly::Client do
432
432
  end
433
433
  end
434
434
 
435
- context "certificate" do
436
- it "#cert should perform a get request" do
437
- @client.should_receive(:get).with("/apps/staging-foo/cert")
438
- @client.cert("staging-foo")
435
+ context "endpoints" do
436
+ it "#endpoints should perform a get request" do
437
+ @client.should_receive(:get).with("/apps/staging-foo/endpoints")
438
+ @client.endpoints("staging-foo")
439
439
  end
440
440
 
441
- it "#create_cert should perform a post request" do
442
- @client.should_receive(:post).with("/apps/staging-foo/cert",
443
- :cert => {:content => 'crt', :key => 'key'})
444
- @client.create_cert("staging-foo", "crt", "key")
441
+ it "#endpoint should perform a get request" do
442
+ @client.should_receive(:get).with("/apps/staging-foo/endpoints/uuid")
443
+ @client.endpoint("staging-foo", 'uuid')
445
444
  end
446
445
 
447
- it "#update_cert should perform a put request" do
448
- @client.should_receive(:put).with("/apps/staging-foo/cert",
449
- :cert => {:content => 'crt', :key => 'key'})
450
- @client.update_cert("staging-foo", "crt", "key")
446
+ it "#create_endpoint should perform a post request" do
447
+ @client.should_receive(:post).with("/apps/staging-foo/endpoints",
448
+ :endpoint => {:certificate => 'crt', :key => 'key', :sni => true})
449
+ @client.create_endpoint("staging-foo", 'crt', 'key', true)
450
+ end
451
+
452
+ it "#update_endpoint should perform a put request" do
453
+ @client.should_receive(:put).with("/apps/staging-foo/endpoints/uuid",
454
+ :endpoint => {:certificate => 'crt', :key => 'key'})
455
+ @client.update_endpoint("staging-foo", 'uuid', 'crt', 'key')
456
+ end
457
+
458
+ it "#delete_endpoint should perform a delete request" do
459
+ @client.should_receive(:delete).with("/apps/staging-foo/endpoints/uuid")
460
+ @client.delete_endpoint('staging-foo', 'uuid')
451
461
  end
452
462
  end
453
463
 
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.38
4
+ version: 0.4.39
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-10-20 00:00:00.000000000 Z
11
+ date: 2014-11-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -257,11 +257,11 @@ files:
257
257
  - lib/shelly/app.rb
258
258
  - lib/shelly/backup.rb
259
259
  - lib/shelly/cli/backup.rb
260
- - lib/shelly/cli/cert.rb
261
260
  - lib/shelly/cli/command.rb
262
261
  - lib/shelly/cli/config.rb
263
262
  - lib/shelly/cli/database.rb
264
263
  - lib/shelly/cli/deploy.rb
264
+ - lib/shelly/cli/endpoint.rb
265
265
  - lib/shelly/cli/errors.rb
266
266
  - lib/shelly/cli/file.rb
267
267
  - lib/shelly/cli/logs.rb
@@ -276,11 +276,11 @@ files:
276
276
  - lib/shelly/client/application_logs.rb
277
277
  - lib/shelly/client/apps.rb
278
278
  - lib/shelly/client/auth.rb
279
- - lib/shelly/client/cert.rb
280
279
  - lib/shelly/client/configs.rb
281
280
  - lib/shelly/client/database_backups.rb
282
281
  - lib/shelly/client/deployment_logs.rb
283
282
  - lib/shelly/client/deploys.rb
283
+ - lib/shelly/client/endpoint.rb
284
284
  - lib/shelly/client/errors.rb
285
285
  - lib/shelly/client/maintenance.rb
286
286
  - lib/shelly/client/organizations.rb
@@ -310,11 +310,11 @@ files:
310
310
  - spec/shelly/app_spec.rb
311
311
  - spec/shelly/backup_spec.rb
312
312
  - spec/shelly/cli/backup_spec.rb
313
- - spec/shelly/cli/cert_spec.rb
314
313
  - spec/shelly/cli/command_spec.rb
315
314
  - spec/shelly/cli/config_spec.rb
316
315
  - spec/shelly/cli/database_spec.rb
317
316
  - spec/shelly/cli/deploy_spec.rb
317
+ - spec/shelly/cli/endpoint_spec.rb
318
318
  - spec/shelly/cli/file_spec.rb
319
319
  - spec/shelly/cli/logs_spec.rb
320
320
  - spec/shelly/cli/main_spec.rb
@@ -353,7 +353,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
353
353
  version: '0'
354
354
  requirements: []
355
355
  rubyforge_project: shelly
356
- rubygems_version: 2.4.2
356
+ rubygems_version: 2.2.2
357
357
  signing_key:
358
358
  specification_version: 4
359
359
  summary: Shelly Cloud command line tool
@@ -363,11 +363,11 @@ test_files:
363
363
  - spec/shelly/app_spec.rb
364
364
  - spec/shelly/backup_spec.rb
365
365
  - spec/shelly/cli/backup_spec.rb
366
- - spec/shelly/cli/cert_spec.rb
367
366
  - spec/shelly/cli/command_spec.rb
368
367
  - spec/shelly/cli/config_spec.rb
369
368
  - spec/shelly/cli/database_spec.rb
370
369
  - spec/shelly/cli/deploy_spec.rb
370
+ - spec/shelly/cli/endpoint_spec.rb
371
371
  - spec/shelly/cli/file_spec.rb
372
372
  - spec/shelly/cli/logs_spec.rb
373
373
  - spec/shelly/cli/main_spec.rb
@@ -1,99 +0,0 @@
1
- require "shelly/cli/command"
2
-
3
- module Shelly
4
- module CLI
5
- class Cert < Command
6
- namespace :cert
7
- include Helpers
8
-
9
- before_hook :logged_in?, :only => [:show, :create, :update]
10
-
11
- class_option :cloud, :type => :string, :aliases => "-c", :desc => "Specify cloud"
12
-
13
- desc "show", "Show current certificate information"
14
- def show
15
- app = multiple_clouds(options[:cloud], "backup list")
16
-
17
- cert = app.cert
18
- say "Issuer: #{cert['info']['issuer']}"
19
- say "Subject: #{cert['info']['subject']}"
20
- say "Not valid before: #{Time.parse(cert['info']['since']).
21
- getlocal.strftime("%Y-%m-%d %H:%M:%S")}"
22
- say "Expires: #{Time.parse(cert['info']['to']).
23
- getlocal.strftime("%Y-%m-%d %H:%M:%S")}"
24
- rescue Client::NotFoundException => e
25
- raise unless e.resource == :certificate
26
- say_error "Certificate not found"
27
- end
28
-
29
- desc "create CERT_PATH KEY_PATH [BUNDLE_PATH]", "Add certificate to your cloud"
30
- long_desc %{
31
- Add certificate to your cloud.\n
32
- CERT_PATH - path to certificate.\n
33
- KEY_PATH - path to private key.\n
34
- BUNDLE_PATH - optional path to certificate bundle path.
35
- }
36
- def create(cert_path, key_path, bundle_path = nil)
37
- app = multiple_clouds(options[:cloud], "cert create CERT_PATH [BUNDLE_PATH] KEY_PATH")
38
-
39
- content = ::File.read(cert_path).strip
40
- bundle = bundle_path ? ::File.read(bundle_path).strip : ""
41
- key = ::File.read(key_path).strip
42
-
43
- content = content + "\n" + bundle
44
- cert = app.create_cert(content, key)
45
-
46
- say "Certificate was added to your cloud", :green
47
- if cert['ip_address']
48
- say "Deploying certificate on front end."
49
- say "Point your domain to private IP address: #{cert['ip_address']}"
50
- else
51
- say "SSL requires certificate and private IP address."
52
- say "Private IP address was requested for your cloud."
53
- say "Support has been notified and will contact you shortly."
54
- end
55
- rescue Client::ValidationException => e
56
- e.each_error { |error| say_error error, :with_exit => false }
57
- exit 1
58
- rescue Client::ConflictException => e
59
- say_error e[:message]
60
- end
61
-
62
- desc "update CERT_PATH KEY_PATH [BUNDLE_PATH]", "Update current certificate"
63
- long_desc %{
64
- Update current certificate.\n
65
- CERT_PATH - path to certificate.\n
66
- KEY_PATH - path to private key.\n
67
- BUNDLE_PATH - optional path to certificate bundle path.
68
- }
69
- def update(cert_path, key_path, bundle_path = nil)
70
- app = multiple_clouds(options[:cloud], "cert update CERT_PATH [BUNDLE_PATH] KEY_PATH")
71
-
72
- content = ::File.read(cert_path).strip
73
- bundle = bundle_path ? ::File.read(bundle_path).strip : ""
74
- key = ::File.read(key_path).strip
75
-
76
- content = content + "\n" + bundle
77
- cert = app.update_cert(content, key)
78
-
79
- say "Certificate was updated", :green
80
- if cert['ip_address']
81
- say "Deploying certificate on front end."
82
- say "Point your domain to private IP address: #{cert['ip_address']}"
83
- else
84
- say "SSL requires certificate and private IP address."
85
- say "Private IP address was requested for your cloud."
86
- say "Support has been notified and will contact you shortly."
87
- end
88
- rescue Client::ValidationException => e
89
- e.each_error { |error| say_error error, :with_exit => false }
90
- exit 1
91
- rescue Client::NotFoundException => e
92
- raise unless e.resource == :certificate
93
- say_error "Certificate not found"
94
- rescue Client::ConflictException => e
95
- say_error e[:message]
96
- end
97
- end
98
- end
99
- end
@@ -1,13 +0,0 @@
1
- class Shelly::Client
2
- def cert(cloud)
3
- get("/apps/#{cloud}/cert")
4
- end
5
-
6
- def create_cert(cloud, content, key)
7
- post("/apps/#{cloud}/cert", :cert => {:content => content, :key => key})
8
- end
9
-
10
- def update_cert(cloud, content, key)
11
- put("/apps/#{cloud}/cert", :cert => {:content => content, :key => key})
12
- end
13
- end
@@ -1,161 +0,0 @@
1
- require "spec_helper"
2
- require "shelly/cli/cert"
3
-
4
- describe Shelly::CLI::Cert do
5
- before do
6
- FileUtils.stub(:chmod)
7
- @cli = Shelly::CLI::Cert.new
8
- Shelly::CLI::Cert.stub(:new).and_return(@cli)
9
- @client = mock
10
- Shelly::Client.stub(:new).and_return(@client)
11
- @client.stub(:authorize!)
12
- FileUtils.mkdir_p("/projects/foo")
13
- Dir.chdir("/projects/foo")
14
- @app = Shelly::App.new("foo-production")
15
- Shelly::App.stub(:new).and_return(@app)
16
- File.open("Cloudfile", 'w') { |f| f.write("foo-production:\n") }
17
- end
18
-
19
- describe "#show" do
20
- it "should description" do
21
- @app.should_receive(:cert).and_return(cert_response)
22
- $stdout.should_receive(:puts).with("Issuer: Some issuer")
23
- $stdout.should_receive(:puts).with("Subject: Some subject")
24
- $stdout.should_receive(:puts).with("Not valid before:"\
25
- " #{Time.parse(cert_response['info']['since']).getlocal.strftime("%Y-%m-%d %H:%M:%S")}")
26
- $stdout.should_receive(:puts).with("Expires:"\
27
- " #{Time.parse(cert_response['info']['to']).getlocal.strftime("%Y-%m-%d %H:%M:%S")}")
28
- invoke(@cli, :show)
29
- end
30
-
31
- context "certificate not found" do
32
- it "should exit" do
33
- exception = Shelly::Client::NotFoundException.new("resource" => "certificate")
34
- @app.should_receive(:cert).and_raise(exception)
35
- $stdout.should_receive(:puts).with(red "Certificate not found")
36
- lambda {
37
- invoke(@cli, :show)
38
- }.should raise_error(SystemExit)
39
- end
40
- end
41
- end
42
-
43
- describe "#create" do
44
- before do
45
- File.stub(:read).with('crt_path').and_return('crt')
46
- File.stub(:read).with('key_path').and_return('key')
47
- File.stub(:read).with('bundle_path').and_return('bundle')
48
- end
49
-
50
- it "should create certificate" do
51
- @app.should_receive(:create_cert).with("crt\nbundle", "key").
52
- and_return(cert_response)
53
- $stdout.should_receive(:puts).with(green "Certificate was added to your cloud")
54
- $stdout.should_receive(:puts).with("Deploying certificate on front end.")
55
- $stdout.should_receive(:puts).with("Point your domain to private IP address: 10.0.0.1")
56
-
57
- invoke(@cli, :create, "crt_path", "key_path", "bundle_path")
58
- end
59
-
60
- it "should create certificate without bundle" do
61
- @app.should_receive(:create_cert).with("crt\n", "key").
62
- and_return(cert_response('ip_address' => nil))
63
-
64
- $stdout.should_receive(:puts).with(green "Certificate was added to your cloud")
65
- $stdout.should_receive(:puts).with("SSL requires certificate and private IP address.")
66
- $stdout.should_receive(:puts).with("Private IP address was requested for your cloud.")
67
- $stdout.should_receive(:puts).with("Support has been notified and will contact you shortly.")
68
-
69
- invoke(@cli, :create, "crt_path", "key_path")
70
- end
71
-
72
- context "validation errors" do
73
- it "should show errors and exit" do
74
- exception = Shelly::Client::ValidationException.new({"errors" => [["key", "is invalid"]]})
75
- @app.should_receive(:create_cert).and_raise(exception)
76
- $stdout.should_receive(:puts).with(red "Key is invalid")
77
-
78
- lambda {
79
- invoke(@cli, :create, "crt_path", "key_path", "bundle_path")
80
- }.should raise_error(SystemExit)
81
- end
82
- end
83
-
84
- context "deployment conflict" do
85
- it "should show errors and exit" do
86
- exception = Shelly::Client::ConflictException.new({"message" => "Deployment is in progress"})
87
- @app.should_receive(:create_cert).and_raise(exception)
88
- $stdout.should_receive(:puts).with(red "Deployment is in progress")
89
-
90
- lambda {
91
- invoke(@cli, :create, "crt_path", "key_path", "bundle_path")
92
- }.should raise_error(SystemExit)
93
- end
94
- end
95
- end
96
-
97
- describe "#update" do
98
- before do
99
- File.stub(:read).with('crt_path').and_return('crt')
100
- File.stub(:read).with('key_path').and_return('key')
101
- File.stub(:read).with('bundle_path').and_return('bundle')
102
- end
103
-
104
- it "should create certificate" do
105
- @app.should_receive(:update_cert).with("crt\nbundle", "key").
106
- and_return(cert_response)
107
- $stdout.should_receive(:puts).with(green "Certificate was updated")
108
- $stdout.should_receive(:puts).with("Deploying certificate on front end.")
109
- $stdout.should_receive(:puts).with("Point your domain to private IP address: 10.0.0.1")
110
-
111
- invoke(@cli, :update, "crt_path", "key_path", "bundle_path")
112
- end
113
-
114
- it "should create certificate without bundle" do
115
- @app.should_receive(:update_cert).with("crt\n", "key").
116
- and_return(cert_response('ip_address' => nil))
117
-
118
- $stdout.should_receive(:puts).with(green "Certificate was updated")
119
- $stdout.should_receive(:puts).with("SSL requires certificate and private IP address.")
120
- $stdout.should_receive(:puts).with("Private IP address was requested for your cloud.")
121
- $stdout.should_receive(:puts).with("Support has been notified and will contact you shortly.")
122
-
123
- invoke(@cli, :update, "crt_path", "key_path")
124
- end
125
-
126
- context "validation errors" do
127
- it "should show errors and exit" do
128
- exception = Shelly::Client::ValidationException.new({"errors" => [["key", "is invalid"]]})
129
- @app.should_receive(:update_cert).and_raise(exception)
130
- $stdout.should_receive(:puts).with(red "Key is invalid")
131
-
132
- lambda {
133
- invoke(@cli, :update, "crt_path", "key_path", "bundle_path")
134
- }.should raise_error(SystemExit)
135
- end
136
- end
137
-
138
- context "deployment conflict" do
139
- it "should show errors and exit" do
140
- exception = Shelly::Client::ConflictException.new({"message" => "Deployment is in progress"})
141
- @app.should_receive(:update_cert).and_raise(exception)
142
- $stdout.should_receive(:puts).with(red "Deployment is in progress")
143
-
144
- lambda {
145
- invoke(@cli, :update, "crt_path", "key_path", "bundle_path")
146
- }.should raise_error(SystemExit)
147
- end
148
- end
149
- end
150
-
151
- def cert_response(options = {})
152
- {
153
- 'info' => {
154
- 'issuer' => 'Some issuer',
155
- 'subject' => 'Some subject',
156
- 'since' => '2012-06-11 23:00:00 UTC',
157
- 'to' => '2013-06-11 11:00:00 UTC'},
158
- 'ip_address' => '10.0.0.1'
159
- }.merge(options)
160
- end
161
- end