shelly 0.0.10 → 0.0.11
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/lib/shelly/app.rb +5 -1
- data/lib/shelly/cli/main.rb +130 -6
- data/lib/shelly/client.rb +11 -10
- data/lib/shelly/user.rb +13 -0
- data/lib/shelly/version.rb +1 -1
- data/spec/shelly/app_spec.rb +13 -0
- data/spec/shelly/cli/main_spec.rb +354 -20
- data/spec/shelly/client_spec.rb +14 -33
- data/spec/shelly/user_spec.rb +35 -0
- metadata +111 -169
- data/lib/shelly/cli/account.rb +0 -61
- data/lib/shelly/cli/apps.rb +0 -90
- data/spec/shelly/cli/account_spec.rb +0 -128
- data/spec/shelly/cli/apps_spec.rb +0 -192
data/lib/shelly/app.rb
CHANGED
@@ -19,8 +19,12 @@ module Shelly
|
|
19
19
|
IO.popen("git remote").read.split("\n").include?(purpose)
|
20
20
|
end
|
21
21
|
|
22
|
+
def git_host
|
23
|
+
ENV["SHELLY_GIT_HOST"] || "git.shellycloud.com"
|
24
|
+
end
|
25
|
+
|
22
26
|
def git_url
|
23
|
-
"git
|
27
|
+
"git@#{git_host}:#{code_name}.git"
|
24
28
|
end
|
25
29
|
|
26
30
|
def generate_cloudfile
|
data/lib/shelly/cli/main.rb
CHANGED
@@ -1,14 +1,11 @@
|
|
1
1
|
require "shelly"
|
2
2
|
require "thor/group"
|
3
|
-
require "shelly/cli/account"
|
4
|
-
require "shelly/cli/apps"
|
5
3
|
|
6
4
|
module Shelly
|
7
5
|
module CLI
|
8
6
|
class Main < Thor
|
9
7
|
include Thor::Actions
|
10
|
-
|
11
|
-
register(Apps, "apps", "apps <command>", "Manages your applications")
|
8
|
+
include Helpers
|
12
9
|
|
13
10
|
map %w(-v --version) => :version
|
14
11
|
desc "version", "Displays shelly version"
|
@@ -18,12 +15,139 @@ module Shelly
|
|
18
15
|
|
19
16
|
desc "register [EMAIL]", "Registers new user account on Shelly Cloud"
|
20
17
|
def register(email = nil)
|
21
|
-
|
18
|
+
say "Registering with email: #{email}" if email
|
19
|
+
user = User.new(email || ask_for_email, ask_for_password)
|
20
|
+
user.register
|
21
|
+
if user.ssh_key_exists?
|
22
|
+
say "Uploading your public SSH key from #{user.ssh_key_path}"
|
23
|
+
end
|
24
|
+
say "Successfully registered!"
|
25
|
+
say "Check you mailbox for email address confirmation"
|
26
|
+
rescue Client::APIError => e
|
27
|
+
if e.message == "Validation Failed"
|
28
|
+
e.errors.each { |error| say "#{error.first} #{error.last}" }
|
29
|
+
exit 1
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "login [EMAIL]", "Logins user to Shelly Cloud"
|
34
|
+
def login(email = nil)
|
35
|
+
user = User.new(email || ask_for_email, ask_for_password(false))
|
36
|
+
user.login
|
37
|
+
say "Login successful"
|
38
|
+
say "Uploading your public SSH key"
|
39
|
+
user.upload_ssh_key
|
40
|
+
rescue RestClient::Unauthorized
|
41
|
+
say "Wrong email or password or your email is unconfirmend"
|
42
|
+
exit 1
|
22
43
|
end
|
23
44
|
|
24
45
|
desc "add", "Adds new application to Shelly Cloud"
|
25
46
|
def add
|
26
|
-
|
47
|
+
say_error "Must be run inside your project git repository" unless App.inside_git_repository?
|
48
|
+
|
49
|
+
@app = Shelly::App.new
|
50
|
+
@app.purpose = ask_for_purpose
|
51
|
+
@app.code_name = ask_for_code_name
|
52
|
+
@app.databases = ask_for_databases
|
53
|
+
@app.create
|
54
|
+
|
55
|
+
unless @app.remote_exists?
|
56
|
+
say "Adding remote #{@app.purpose} #{@app.git_url}", :green
|
57
|
+
@app.add_git_remote
|
58
|
+
else
|
59
|
+
say "Remote #{@app.purpose} already exists"
|
60
|
+
if yes?("Would you like to overwrite remote #{@app.purpose} with #{@app.git_url} (Y/N)?:")
|
61
|
+
@app.add_git_remote(true)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
say "Creating Cloudfile", :green
|
66
|
+
@app.create_cloudfile
|
67
|
+
|
68
|
+
say "Provide billing details. Opening browser...", :green
|
69
|
+
@app.open_billing_page
|
70
|
+
|
71
|
+
info_adding_cloudfile_to_repository
|
72
|
+
info_deploying_to_shellycloud
|
73
|
+
rescue Client::APIError => e
|
74
|
+
if e.message == "Validation Failed"
|
75
|
+
e.errors.each { |error| say "#{error.first} #{error.last}" }
|
76
|
+
exit 1
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
# FIXME: move to helpers
|
82
|
+
no_tasks do
|
83
|
+
def ask_for_email
|
84
|
+
email_question = User.guess_email.blank? ? "Email:" : "Email (#{User.guess_email} - default):"
|
85
|
+
email = ask(email_question)
|
86
|
+
email = email.blank? ? User.guess_email : email
|
87
|
+
return email if email.present?
|
88
|
+
say_error "Email can't be blank, please try again"
|
89
|
+
end
|
90
|
+
|
91
|
+
def ask_for_password(with_confirmation = true)
|
92
|
+
loop do
|
93
|
+
say "Password: "
|
94
|
+
password = echo_disabled { $stdin.gets.strip }
|
95
|
+
say_new_line
|
96
|
+
return password unless with_confirmation
|
97
|
+
say "Password confirmation: "
|
98
|
+
password_confirmation = echo_disabled { $stdin.gets.strip }
|
99
|
+
say_new_line
|
100
|
+
if password.present?
|
101
|
+
return password if password == password_confirmation
|
102
|
+
say "Password and password confirmation don't match, please type them again"
|
103
|
+
else
|
104
|
+
say "Password can't be blank"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def ask_for_purpose
|
110
|
+
purpose = ask("How will you use this system (production - default,staging):")
|
111
|
+
purpose.blank? ? "production" : purpose
|
112
|
+
end
|
113
|
+
|
114
|
+
def ask_for_code_name
|
115
|
+
default_code_name = "#{Shelly::App.guess_code_name}-#{@app.purpose}"
|
116
|
+
code_name = ask("Application code name (#{default_code_name} - default):")
|
117
|
+
code_name.blank? ? default_code_name : code_name
|
118
|
+
end
|
119
|
+
|
120
|
+
def ask_for_databases
|
121
|
+
kinds = Shelly::App::DATABASE_KINDS
|
122
|
+
databases = ask("Which database do you want to use #{kinds.join(", ")} (postgresql - default):")
|
123
|
+
begin
|
124
|
+
databases = databases.split(/[\s,]/)
|
125
|
+
valid = databases.all? { |kind| kinds.include?(kind) }
|
126
|
+
break if valid
|
127
|
+
databases = ask("Unknown database kind. Supported are: #{kinds.join(", ")}:")
|
128
|
+
end while not valid
|
129
|
+
|
130
|
+
databases.empty? ? ["postgresql"] : databases
|
131
|
+
end
|
132
|
+
|
133
|
+
def info_adding_cloudfile_to_repository
|
134
|
+
say_new_line
|
135
|
+
say "Project is now configured for use with Shell Cloud:", :green
|
136
|
+
say "You can review changes using", :green
|
137
|
+
say " git status"
|
138
|
+
end
|
139
|
+
|
140
|
+
def info_deploying_to_shellycloud
|
141
|
+
say_new_line
|
142
|
+
say "When you make sure all settings are correct please issue following commands:", :green
|
143
|
+
say " git add ."
|
144
|
+
say ' git commit -m "Application added to Shelly Cloud"'
|
145
|
+
say " git push"
|
146
|
+
say_new_line
|
147
|
+
say "Deploy to #{@app.purpose} using:", :green
|
148
|
+
say " git push #{@app.purpose} master"
|
149
|
+
say_new_line
|
150
|
+
end
|
27
151
|
end
|
28
152
|
end
|
29
153
|
end
|
data/lib/shelly/client.rb
CHANGED
@@ -3,8 +3,6 @@ require "json"
|
|
3
3
|
|
4
4
|
module Shelly
|
5
5
|
class Client
|
6
|
-
class UnauthorizedException < Exception; end
|
7
|
-
class UnsupportedResponseException < Exception; end
|
8
6
|
class APIError < Exception
|
9
7
|
def initialize(response)
|
10
8
|
@response = response
|
@@ -40,10 +38,18 @@ module Shelly
|
|
40
38
|
post("/apps", :app => attributes)
|
41
39
|
end
|
42
40
|
|
41
|
+
def update_ssh_key(ssh_key)
|
42
|
+
put("/ssh_key", :ssh_key => ssh_key)
|
43
|
+
end
|
44
|
+
|
43
45
|
def post(path, params = {})
|
44
46
|
request(path, :post, params)
|
45
47
|
end
|
46
48
|
|
49
|
+
def put(path, params = {})
|
50
|
+
request(path, :put, params)
|
51
|
+
end
|
52
|
+
|
47
53
|
def get(path)
|
48
54
|
request(path, :get)
|
49
55
|
end
|
@@ -74,19 +80,14 @@ module Shelly
|
|
74
80
|
end
|
75
81
|
|
76
82
|
def process_response(response)
|
77
|
-
raise UnauthorizedException.new if response.code == 302
|
78
83
|
if [404, 422, 500].include?(response.code)
|
84
|
+
# FIXME: move parsing JSON to APIError class
|
79
85
|
error_details = JSON.parse(response.body)
|
80
86
|
raise APIError.new(error_details)
|
81
87
|
end
|
82
88
|
|
83
|
-
|
84
|
-
|
85
|
-
JSON.parse(response.body)
|
86
|
-
rescue RestClient::RequestFailed => e
|
87
|
-
raise UnauthorizedException.new if e.http_code == 406
|
88
|
-
raise UnsupportedResponseException.new(e)
|
89
|
-
end
|
89
|
+
response.return!
|
90
|
+
JSON.parse(response.body)
|
90
91
|
end
|
91
92
|
end
|
92
93
|
end
|
data/lib/shelly/user.rb
CHANGED
@@ -13,6 +13,14 @@ module Shelly
|
|
13
13
|
save_credentials
|
14
14
|
end
|
15
15
|
|
16
|
+
def login
|
17
|
+
client = Client.new(email, password)
|
18
|
+
# test if credentials are valid
|
19
|
+
# if not RestClient::Unauthorized will be raised
|
20
|
+
client.token
|
21
|
+
save_credentials
|
22
|
+
end
|
23
|
+
|
16
24
|
def token
|
17
25
|
shelly.token["token"]
|
18
26
|
end
|
@@ -44,6 +52,11 @@ module Shelly
|
|
44
52
|
File.expand_path("~/.shelly")
|
45
53
|
end
|
46
54
|
|
55
|
+
def upload_ssh_key
|
56
|
+
key = File.read(ssh_key_path)
|
57
|
+
shelly.update_ssh_key(key)
|
58
|
+
end
|
59
|
+
|
47
60
|
protected
|
48
61
|
def credentials_path
|
49
62
|
File.join(config_dir, "credentials")
|
data/lib/shelly/version.rb
CHANGED
data/spec/shelly/app_spec.rb
CHANGED
@@ -136,4 +136,17 @@ config
|
|
136
136
|
end
|
137
137
|
end
|
138
138
|
end
|
139
|
+
|
140
|
+
describe "#git_host" do
|
141
|
+
it "should return default git host" do
|
142
|
+
@app.git_host.should == "git.shellycloud.com"
|
143
|
+
end
|
144
|
+
|
145
|
+
context "SHELLY_GIT_HOST set" do
|
146
|
+
it "should return value of SHELLY_GIT_HOST env variable" do
|
147
|
+
ENV['SHELLY_GIT_HOST'] = "git.example.com"
|
148
|
+
@app.git_host.should == "git.example.com"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
139
152
|
end
|
@@ -3,7 +3,14 @@ require "shelly/cli/main"
|
|
3
3
|
|
4
4
|
describe Shelly::CLI::Main do
|
5
5
|
before do
|
6
|
+
ENV['SHELLY_GIT_HOST'] = nil
|
7
|
+
FileUtils.stub(:chmod)
|
6
8
|
@main = Shelly::CLI::Main.new
|
9
|
+
@client = mock
|
10
|
+
Shelly::Client.stub(:new).and_return(@client)
|
11
|
+
Shelly::User.stub(:guess_email).and_return("")
|
12
|
+
$stdout.stub(:puts)
|
13
|
+
$stdout.stub(:print)
|
7
14
|
end
|
8
15
|
|
9
16
|
describe "#version" do
|
@@ -13,33 +20,360 @@ describe Shelly::CLI::Main do
|
|
13
20
|
end
|
14
21
|
end
|
15
22
|
|
16
|
-
describe "#register" do
|
17
|
-
it "should invoke account:register command" do
|
18
|
-
@main.should_receive(:invoke).with("account:register", "kate@example.com")
|
19
|
-
@main.register("kate@example.com")
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
describe "#add" do
|
24
|
-
it "should invoke apps:add command" do
|
25
|
-
@main.should_receive(:invoke).with("apps:add")
|
26
|
-
@main.add
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
23
|
describe "#help" do
|
31
24
|
it "should display available commands" do
|
32
25
|
expected = <<-OUT
|
33
26
|
Tasks:
|
34
|
-
shelly
|
35
|
-
shelly
|
36
|
-
shelly
|
37
|
-
shelly
|
38
|
-
shelly
|
39
|
-
shelly version # Displays shelly version
|
27
|
+
shelly add # Adds new application to Shelly Cloud
|
28
|
+
shelly help [TASK] # Describe available tasks or one specific task
|
29
|
+
shelly login [EMAIL] # Logins user to Shelly Cloud
|
30
|
+
shelly register [EMAIL] # Registers new user account on Shelly Cloud
|
31
|
+
shelly version # Displays shelly version
|
40
32
|
OUT
|
41
33
|
out = IO.popen("bin/shelly").read.strip
|
42
34
|
out.should == expected.strip
|
43
35
|
end
|
44
36
|
end
|
37
|
+
|
38
|
+
describe "#register" do
|
39
|
+
before do
|
40
|
+
@client.stub(:register_user)
|
41
|
+
@key_path = File.expand_path("~/.ssh/id_rsa.pub")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should ask for email, password and password confirmation" do
|
45
|
+
$stdout.should_receive(:print).with("Email: ")
|
46
|
+
$stdout.should_receive(:print).with("Password: ")
|
47
|
+
$stdout.should_receive(:print).with("Password confirmation: ")
|
48
|
+
fake_stdin(["better@example.com", "secret", "secret"]) do
|
49
|
+
@main.register
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should suggest email and use it if user enters blank email" do
|
54
|
+
Shelly::User.stub(:guess_email).and_return("kate@example.com")
|
55
|
+
$stdout.should_receive(:print).with("Email (kate@example.com - default): ")
|
56
|
+
@client.should_receive(:register_user).with("kate@example.com", "secret", nil)
|
57
|
+
fake_stdin(["", "secret", "secret"]) do
|
58
|
+
@main.register
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should use email provided by user" do
|
63
|
+
@client.should_receive(:register_user).with("better@example.com", "secret", nil)
|
64
|
+
fake_stdin(["better@example.com", "secret", "secret"]) do
|
65
|
+
@main.register
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should not ask about email if it's provided as argument" do
|
70
|
+
$stdout.should_receive(:puts).with("Registering with email: kate@example.com")
|
71
|
+
fake_stdin(["secret", "secret"]) do
|
72
|
+
@main.register("kate@example.com")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "when user enters blank email" do
|
77
|
+
it "should show error message and exit with 1" do
|
78
|
+
Shelly::User.stub(:guess_email).and_return("")
|
79
|
+
$stdout.should_receive(:puts).with("Email can't be blank, please try again")
|
80
|
+
lambda {
|
81
|
+
fake_stdin(["", "bob@example.com", "only-pass", "only-pass"]) do
|
82
|
+
@main.register
|
83
|
+
end
|
84
|
+
}.should raise_error(SystemExit)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context "when user enters blank password" do
|
89
|
+
it "should ask for it again" do
|
90
|
+
$stdout.should_receive(:puts).with("Password can't be blank")
|
91
|
+
fake_stdin(["better@example.com", "", "", "secret", "secret"]) do
|
92
|
+
@main.register
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "when user enters password and password confirmation which don't match each other" do
|
98
|
+
it "should ask for them again" do
|
99
|
+
$stdout.should_receive(:puts).with("Password and password confirmation don't match, please type them again")
|
100
|
+
fake_stdin(["better@example.com", "secret", "sec-TYPO-ret", "secret", "secret"]) do
|
101
|
+
@main.register
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "public SSH key exists" do
|
107
|
+
it "should register with the public SSH key" do
|
108
|
+
FileUtils.mkdir_p("~/.ssh")
|
109
|
+
File.open(@key_path, "w") { |f| f << "key" }
|
110
|
+
$stdout.should_receive(:puts).with("Uploading your public SSH key from #{@key_path}")
|
111
|
+
fake_stdin(["kate@example.com", "secret", "secret"]) do
|
112
|
+
@main.register
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context "public SSH key doesn't exist" do
|
118
|
+
it "should register user without the public SSH key" do
|
119
|
+
$stdout.should_not_receive(:puts).with("Uploading your public SSH key from #{@key_path}")
|
120
|
+
fake_stdin(["kate@example.com", "secret", "secret"]) do
|
121
|
+
@main.register
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context "on successful registration" do
|
127
|
+
it "should display message about registration and email address confirmation" do
|
128
|
+
@client.stub(:register_user).and_return(true)
|
129
|
+
$stdout.should_receive(:puts).with("Successfully registered!")
|
130
|
+
$stdout.should_receive(:puts).with("Check you mailbox for email address confirmation")
|
131
|
+
fake_stdin(["kate@example.com", "pass", "pass"]) do
|
132
|
+
@main.register
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context "on unsuccessful registration" do
|
138
|
+
it "should display errors and exit with 1" do
|
139
|
+
response = {"message" => "Validation Failed", "errors" => [["email", "has been already taken"]]}
|
140
|
+
exception = Shelly::Client::APIError.new(response)
|
141
|
+
@client.stub(:register_user).and_raise(exception)
|
142
|
+
$stdout.should_receive(:puts).with("email has been already taken")
|
143
|
+
lambda {
|
144
|
+
fake_stdin(["kate@example.com", "pass", "pass"]) do
|
145
|
+
@main.register
|
146
|
+
end
|
147
|
+
}.should raise_error(SystemExit)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
describe "#login" do
|
153
|
+
before do
|
154
|
+
@user = Shelly::User.new
|
155
|
+
@user.stub(:upload_ssh_key)
|
156
|
+
@client.stub(:token).and_return("abc")
|
157
|
+
Shelly::User.stub(:new).and_return(@user)
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should ask about email and password" do
|
161
|
+
fake_stdin(["megan@example.com", "secret"]) do
|
162
|
+
@main.login
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
context "on successful login" do
|
167
|
+
it "should display message about successful login" do
|
168
|
+
$stdout.should_receive(:puts).with("Login successful")
|
169
|
+
fake_stdin(["megan@example.com", "secret"]) do
|
170
|
+
@main.login
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should upload user's public SSH key" do
|
175
|
+
@user.should_receive(:upload_ssh_key)
|
176
|
+
$stdout.should_receive(:puts).with("Uploading your public SSH key")
|
177
|
+
fake_stdin(["megan@example.com", "secret"]) do
|
178
|
+
@main.login
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should display list of applications to which user has access"
|
183
|
+
end
|
184
|
+
|
185
|
+
context "on unauthorized user" do
|
186
|
+
it "should exit with 1 and display error message" do
|
187
|
+
exception = RestClient::Unauthorized.new
|
188
|
+
@client.stub(:token).and_raise(exception)
|
189
|
+
$stdout.should_receive(:puts).with("Wrong email or password or your email is unconfirmend")
|
190
|
+
lambda {
|
191
|
+
fake_stdin(["megan@example.com", "secret"]) do
|
192
|
+
@main.login
|
193
|
+
end
|
194
|
+
}.should raise_error(SystemExit)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
describe "#add" do
|
200
|
+
before do
|
201
|
+
FileUtils.mkdir_p("/projects/foo")
|
202
|
+
Dir.chdir("/projects/foo")
|
203
|
+
@app = Shelly::App.new
|
204
|
+
@app.stub(:add_git_remote)
|
205
|
+
@app.stub(:create)
|
206
|
+
@app.stub(:generate_cloudfile).and_return("Example Cloudfile")
|
207
|
+
@app.stub(:open_billing_page)
|
208
|
+
@app.stub(:remote_exists?).and_return(false)
|
209
|
+
Shelly::App.stub(:inside_git_repository?).and_return(true)
|
210
|
+
Shelly::App.stub(:new).and_return(@app)
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should exit with message if command run outside git repository" do
|
214
|
+
Shelly::App.stub(:inside_git_repository?).and_return(false)
|
215
|
+
$stdout.should_receive(:puts).with("Must be run inside your project git repository")
|
216
|
+
lambda {
|
217
|
+
fake_stdin(["staging", "", ""]) do
|
218
|
+
@main.add
|
219
|
+
end
|
220
|
+
}.should raise_error(SystemExit)
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should ask user how he will use application" do
|
224
|
+
$stdout.should_receive(:print).with("How will you use this system (production - default,staging): ")
|
225
|
+
@app.should_receive(:purpose=).with("staging")
|
226
|
+
fake_stdin(["staging", "", ""]) do
|
227
|
+
@main.add
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
context "when user provided empty purpose" do
|
232
|
+
it "should use 'production' as default" do
|
233
|
+
$stdout.should_receive(:print).with("How will you use this system (production - default,staging): ")
|
234
|
+
@app.should_receive(:purpose=).with("production")
|
235
|
+
fake_stdin(["", "", ""]) do
|
236
|
+
@main.add
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
it "should use code name provided by user" do
|
242
|
+
$stdout.should_receive(:print).with("How will you use this system (production - default,staging): ")
|
243
|
+
$stdout.should_receive(:print).with("Application code name (foo-staging - default): ")
|
244
|
+
@app.should_receive(:code_name=).with("mycodename")
|
245
|
+
fake_stdin(["staging", "mycodename", ""]) do
|
246
|
+
@main.add
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
context "when user provided empty code name" do
|
251
|
+
it "should use 'current_dirname-purpose' as default" do
|
252
|
+
$stdout.should_receive(:print).with("How will you use this system (production - default,staging): ")
|
253
|
+
$stdout.should_receive(:print).with("Application code name (foo-staging - default): ")
|
254
|
+
fake_stdin(["staging", "", ""]) do
|
255
|
+
@main.add
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
it "should use database provided by user (separated by comma or space)" do
|
261
|
+
$stdout.should_receive(:print).with("Which database do you want to use postgresql, mongodb, redis, none (postgresql - default): ")
|
262
|
+
@app.should_receive(:databases=).with(["postgresql", "mongodb", "redis"])
|
263
|
+
fake_stdin(["staging", "", "postgresql,mongodb redis"]) do
|
264
|
+
@main.add
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
it "should ask again for databases if unsupported kind typed" do
|
269
|
+
$stdout.should_receive(:print).with("Which database do you want to use postgresql, mongodb, redis, none (postgresql - default): ")
|
270
|
+
$stdout.should_receive(:print).with("Unknown database kind. Supported are: postgresql, mongodb, redis, none: ")
|
271
|
+
fake_stdin(["staging", "", "postgresql,doesnt-exist", "none"]) do
|
272
|
+
@main.add
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
context "when user provided empty database" do
|
277
|
+
it "should use 'postgresql' database as default" do
|
278
|
+
@app.should_receive(:databases=).with(["postgresql"])
|
279
|
+
fake_stdin(["staging", "", ""]) do
|
280
|
+
@main.add
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
it "should create the app on shelly cloud" do
|
286
|
+
@app.should_receive(:create)
|
287
|
+
fake_stdin(["", "", ""]) do
|
288
|
+
@main.add
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
it "should display validation errors if they are any" do
|
293
|
+
response = {"message" => "Validation Failed", "errors" => [["code_name", "has been already taken"]]}
|
294
|
+
exception = Shelly::Client::APIError.new(response)
|
295
|
+
@app.should_receive(:create).and_raise(exception)
|
296
|
+
$stdout.should_receive(:puts).with("code_name has been already taken")
|
297
|
+
lambda {
|
298
|
+
fake_stdin(["", "", ""]) do
|
299
|
+
@main.add
|
300
|
+
end
|
301
|
+
}.should raise_error(SystemExit)
|
302
|
+
end
|
303
|
+
|
304
|
+
context "git remote doesn't exist" do
|
305
|
+
it "should add git remote" do
|
306
|
+
$stdout.should_receive(:puts).with("\e[32mAdding remote staging git@git.shellycloud.com:foooo.git\e[0m")
|
307
|
+
@app.should_receive(:add_git_remote)
|
308
|
+
fake_stdin(["staging", "foooo", ""]) do
|
309
|
+
@main.add
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
context "git remote exist" do
|
315
|
+
before do
|
316
|
+
@app.stub(:remote_exists?).and_return(true)
|
317
|
+
end
|
318
|
+
|
319
|
+
it "should ask user if he wants to overwrite existing git remote" do
|
320
|
+
$stdout.should_receive(:puts).with("Remote staging already exists")
|
321
|
+
$stdout.should_receive(:print).with("Would you like to overwrite remote staging with git@git.shellycloud.com:foooo.git (Y/N)?: ")
|
322
|
+
fake_stdin(["staging", "foooo", "", "y"]) do
|
323
|
+
@main.add
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
it "should overwrite existing git remote on 'yes' from user" do
|
328
|
+
@app.should_receive(:add_git_remote).with(true)
|
329
|
+
fake_stdin(["staging", "foooo", "", "y"]) do
|
330
|
+
@main.add
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
it "should not overwrite existing git remote on 'no' from user" do
|
335
|
+
@app.should_not_receive(:add_git_remote).with(true)
|
336
|
+
fake_stdin(["staging", "foooo", "", "n"]) do
|
337
|
+
@main.add
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
it "should create Cloudfile" do
|
343
|
+
File.exists?("/projects/foo/Cloudfile").should be_false
|
344
|
+
fake_stdin(["staging", "foooo", ""]) do
|
345
|
+
@main.add
|
346
|
+
end
|
347
|
+
File.read("/projects/foo/Cloudfile").should == "Example Cloudfile"
|
348
|
+
end
|
349
|
+
|
350
|
+
it "should browser window with link to edit billing information" do
|
351
|
+
$stdout.should_receive(:puts).with("\e[32mProvide billing details. Opening browser...\e[0m")
|
352
|
+
@app.should_receive(:open_billing_page)
|
353
|
+
fake_stdin(["staging", "foooo", ""]) do
|
354
|
+
@main.add
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
it "should display info about adding Cloudfile to repository" do
|
359
|
+
$stdout.should_receive(:puts).with("\e[32mProject is now configured for use with Shell Cloud:\e[0m")
|
360
|
+
$stdout.should_receive(:puts).with("\e[32mYou can review changes using\e[0m")
|
361
|
+
$stdout.should_receive(:puts).with(" git status")
|
362
|
+
fake_stdin(["staging", "foooo", "none"]) do
|
363
|
+
@main.add
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
it "should display info on how to deploy to ShellyCloud" do
|
368
|
+
$stdout.should_receive(:puts).with("\e[32mWhen you make sure all settings are correct please issue following commands:\e[0m")
|
369
|
+
$stdout.should_receive(:puts).with(" git add .")
|
370
|
+
$stdout.should_receive(:puts).with(' git commit -m "Application added to Shelly Cloud"')
|
371
|
+
$stdout.should_receive(:puts).with(" git push")
|
372
|
+
$stdout.should_receive(:puts).with("\e[32mDeploy to staging using:\e[0m")
|
373
|
+
$stdout.should_receive(:puts).with(" git push staging master")
|
374
|
+
fake_stdin(["staging", "foooo", "none"]) do
|
375
|
+
@main.add
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
45
379
|
end
|