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/cli/account.rb
DELETED
@@ -1,61 +0,0 @@
|
|
1
|
-
require "shelly/user"
|
2
|
-
|
3
|
-
module Shelly
|
4
|
-
module CLI
|
5
|
-
class Account < Thor
|
6
|
-
namespace :account
|
7
|
-
include Helpers
|
8
|
-
|
9
|
-
desc "register [EMAIL]", "Registers new user account on Shelly Cloud"
|
10
|
-
def register(email = nil)
|
11
|
-
say "Registering with email: #{email}" if email
|
12
|
-
user = User.new(email || ask_for_email, ask_for_password)
|
13
|
-
user.register
|
14
|
-
if user.ssh_key_exists?
|
15
|
-
say "Uploading your public SSH key from #{user.ssh_key_path}"
|
16
|
-
end
|
17
|
-
say "Successfully registered!"
|
18
|
-
say "Check you mailbox for email address confirmation"
|
19
|
-
rescue Client::APIError => e
|
20
|
-
if e.message == "Validation Failed"
|
21
|
-
e.errors.each { |error| say "#{error.first} #{error.last}" }
|
22
|
-
exit 1
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
# Fix for bug with displaying help for subcommands
|
27
|
-
# http://stackoverflow.com/questions/5663519/namespacing-thor-commands-in-a-standalone-ruby-executable
|
28
|
-
def self.banner(task, namespace = true, subcommand = false)
|
29
|
-
"#{basename} #{task.formatted_usage(self, true, subcommand)}"
|
30
|
-
end
|
31
|
-
|
32
|
-
# FIXME: move to helpers
|
33
|
-
no_tasks do
|
34
|
-
def ask_for_email
|
35
|
-
email_question = User.guess_email.blank? ? "Email:" : "Email (#{User.guess_email} - default):"
|
36
|
-
email = ask(email_question)
|
37
|
-
email = email.blank? ? User.guess_email : email
|
38
|
-
return email if email.present?
|
39
|
-
say_error "Email can't be blank, please try again"
|
40
|
-
end
|
41
|
-
|
42
|
-
def ask_for_password
|
43
|
-
loop do
|
44
|
-
say "Password: "
|
45
|
-
password = echo_disabled { $stdin.gets.strip }
|
46
|
-
say_new_line
|
47
|
-
say "Password confirmation: "
|
48
|
-
password_confirmation = echo_disabled { $stdin.gets.strip }
|
49
|
-
say_new_line
|
50
|
-
if password.present?
|
51
|
-
return password if password == password_confirmation
|
52
|
-
say "Password and password confirmation don't match, please type them again"
|
53
|
-
else
|
54
|
-
say "Password can't be blank"
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
data/lib/shelly/cli/apps.rb
DELETED
@@ -1,90 +0,0 @@
|
|
1
|
-
require "shelly/app"
|
2
|
-
|
3
|
-
module Shelly
|
4
|
-
module CLI
|
5
|
-
class Apps < Thor
|
6
|
-
include Helpers
|
7
|
-
namespace :apps
|
8
|
-
|
9
|
-
desc "add", "Adds new application to Shelly Cloud"
|
10
|
-
def add
|
11
|
-
say_error "Must be run inside your project git repository" unless App.inside_git_repository?
|
12
|
-
|
13
|
-
@app = Shelly::App.new
|
14
|
-
@app.purpose = ask_for_purpose
|
15
|
-
@app.code_name = ask_for_code_name
|
16
|
-
@app.databases = ask_for_databases
|
17
|
-
@app.create
|
18
|
-
|
19
|
-
unless @app.remote_exists?
|
20
|
-
say "Adding remote #{@app.purpose} #{@app.git_url}", :green
|
21
|
-
@app.add_git_remote
|
22
|
-
else
|
23
|
-
say "Remote #{@app.purpose} already exists"
|
24
|
-
if yes?("Would you like to overwrite remote #{@app.purpose} with #{@app.git_url} (Y/N)?:")
|
25
|
-
@app.add_git_remote(true)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
say "Creating Cloudfile", :green
|
30
|
-
@app.create_cloudfile
|
31
|
-
|
32
|
-
say "Provide billing details. Opening browser...", :green
|
33
|
-
@app.open_billing_page
|
34
|
-
|
35
|
-
info_adding_cloudfile_to_repository
|
36
|
-
info_deploying_to_shellycloud
|
37
|
-
rescue Client::APIError => e
|
38
|
-
if e.message == "Validation Failed"
|
39
|
-
e.errors.each { |error| say "#{error.first} #{error.last}" }
|
40
|
-
exit 1
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
no_tasks do
|
45
|
-
def ask_for_purpose
|
46
|
-
purpose = ask("How will you use this system (production - default,staging):")
|
47
|
-
purpose.blank? ? "production" : purpose
|
48
|
-
end
|
49
|
-
|
50
|
-
def ask_for_code_name
|
51
|
-
default_code_name = "#{Shelly::App.guess_code_name}-#{@app.purpose}"
|
52
|
-
code_name = ask("Application code name (#{default_code_name} - default):")
|
53
|
-
code_name.blank? ? default_code_name : code_name
|
54
|
-
end
|
55
|
-
|
56
|
-
def ask_for_databases
|
57
|
-
kinds = Shelly::App::DATABASE_KINDS
|
58
|
-
databases = ask("Which database do you want to use #{kinds.join(", ")} (postgresql - default):")
|
59
|
-
begin
|
60
|
-
databases = databases.split(/[\s,]/)
|
61
|
-
valid = databases.all? { |kind| kinds.include?(kind) }
|
62
|
-
break if valid
|
63
|
-
databases = ask("Unknown database kind. Supported are: #{kinds.join(", ")}:")
|
64
|
-
end while not valid
|
65
|
-
|
66
|
-
databases.empty? ? ["postgresql"] : databases
|
67
|
-
end
|
68
|
-
|
69
|
-
def info_adding_cloudfile_to_repository
|
70
|
-
say_new_line
|
71
|
-
say "Project is now configured for use with Shell Cloud:", :green
|
72
|
-
say "You can review changes using", :green
|
73
|
-
say " git diff"
|
74
|
-
end
|
75
|
-
|
76
|
-
def info_deploying_to_shellycloud
|
77
|
-
say_new_line
|
78
|
-
say "When you make sure all settings are correct please issue following commands:", :green
|
79
|
-
say " git add ."
|
80
|
-
say ' git commit -m "Application added to Shelly Cloud"'
|
81
|
-
say " git push"
|
82
|
-
say_new_line
|
83
|
-
say "Deploy to #{@app.purpose} using:", :green
|
84
|
-
say " git push #{@app.purpose} master"
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
@@ -1,128 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
require "shelly/cli/account"
|
3
|
-
|
4
|
-
describe Shelly::CLI::Account do
|
5
|
-
before do
|
6
|
-
FileUtils.stub(:chmod)
|
7
|
-
@client = mock
|
8
|
-
@account = Shelly::CLI::Account.new
|
9
|
-
Shelly::Client.stub(:new).and_return(@client)
|
10
|
-
$stdout.stub(:puts)
|
11
|
-
$stdout.stub(:print)
|
12
|
-
end
|
13
|
-
|
14
|
-
describe "#register" do
|
15
|
-
before do
|
16
|
-
Shelly::User.stub(:guess_email).and_return("")
|
17
|
-
@client.stub(:register_user)
|
18
|
-
@key_path = File.expand_path("~/.ssh/id_rsa.pub")
|
19
|
-
end
|
20
|
-
|
21
|
-
it "should ask for email, password and password confirmation" do
|
22
|
-
$stdout.should_receive(:print).with("Email: ")
|
23
|
-
$stdout.should_receive(:print).with("Password: ")
|
24
|
-
$stdout.should_receive(:print).with("Password confirmation: ")
|
25
|
-
fake_stdin(["better@example.com", "secret", "secret"]) do
|
26
|
-
@account.register
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
it "should suggest email and use it if user enters blank email" do
|
31
|
-
Shelly::User.stub(:guess_email).and_return("kate@example.com")
|
32
|
-
$stdout.should_receive(:print).with("Email (kate@example.com - default): ")
|
33
|
-
@client.should_receive(:register_user).with("kate@example.com", "secret", nil)
|
34
|
-
fake_stdin(["", "secret", "secret"]) do
|
35
|
-
@account.register
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
it "should use email provided by user" do
|
40
|
-
@client.should_receive(:register_user).with("better@example.com", "secret", nil)
|
41
|
-
fake_stdin(["better@example.com", "secret", "secret"]) do
|
42
|
-
@account.register
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
it "should not ask about email if it's provided as argument" do
|
47
|
-
$stdout.should_receive(:puts).with("Registering with email: kate@example.com")
|
48
|
-
fake_stdin(["secret", "secret"]) do
|
49
|
-
@account.register("kate@example.com")
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
context "when user enters blank email" do
|
54
|
-
it "should show error message and exit with 1" do
|
55
|
-
Shelly::User.stub(:guess_email).and_return("")
|
56
|
-
$stdout.should_receive(:puts).with("Email can't be blank, please try again")
|
57
|
-
lambda {
|
58
|
-
fake_stdin(["", "bob@example.com", "only-pass", "only-pass"]) do
|
59
|
-
@account.register
|
60
|
-
end
|
61
|
-
}.should raise_error(SystemExit)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
context "when user enters blank password" do
|
66
|
-
it "should ask for it again" do
|
67
|
-
$stdout.should_receive(:puts).with("Password can't be blank")
|
68
|
-
fake_stdin(["better@example.com", "", "", "secret", "secret"]) do
|
69
|
-
@account.register
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
context "when user enters password and password confirmation which don't match each other" do
|
75
|
-
it "should ask for them again" do
|
76
|
-
$stdout.should_receive(:puts).with("Password and password confirmation don't match, please type them again")
|
77
|
-
fake_stdin(["better@example.com", "secret", "sec-TYPO-ret", "secret", "secret"]) do
|
78
|
-
@account.register
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
context "public SSH key exists" do
|
84
|
-
it "should register with the public SSH key" do
|
85
|
-
FileUtils.mkdir_p("~/.ssh")
|
86
|
-
File.open(@key_path, "w") { |f| f << "key" }
|
87
|
-
$stdout.should_receive(:puts).with("Uploading your public SSH key from #{@key_path}")
|
88
|
-
fake_stdin(["kate@example.com", "secret", "secret"]) do
|
89
|
-
@account.register
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
context "public SSH key doesn't exist" do
|
95
|
-
it "should register user without the public SSH key" do
|
96
|
-
$stdout.should_not_receive(:puts).with("Uploading your public SSH key from #{@key_path}")
|
97
|
-
fake_stdin(["kate@example.com", "secret", "secret"]) do
|
98
|
-
@account.register
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
context "on successful registration" do
|
104
|
-
it "should display message about registration and email address confirmation" do
|
105
|
-
@client.stub(:register_user).and_return(true)
|
106
|
-
$stdout.should_receive(:puts).with("Successfully registered!")
|
107
|
-
$stdout.should_receive(:puts).with("Check you mailbox for email address confirmation")
|
108
|
-
fake_stdin(["kate@example.com", "pass", "pass"]) do
|
109
|
-
@account.register
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
context "on unsuccessful registration" do
|
115
|
-
it "should display errors and exit with 1" do
|
116
|
-
response = {"message" => "Validation Failed", "errors" => [["email", "has been already taken"]]}
|
117
|
-
exception = Shelly::Client::APIError.new(response)
|
118
|
-
@client.stub(:register_user).and_raise(exception)
|
119
|
-
$stdout.should_receive(:puts).with("email has been already taken")
|
120
|
-
lambda {
|
121
|
-
fake_stdin(["kate@example.com", "pass", "pass"]) do
|
122
|
-
@account.register
|
123
|
-
end
|
124
|
-
}.should raise_error(SystemExit)
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
@@ -1,192 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
require "shelly/cli/apps"
|
3
|
-
|
4
|
-
describe Shelly::CLI::Apps do
|
5
|
-
before do
|
6
|
-
@apps = Shelly::CLI::Apps.new
|
7
|
-
$stdout.stub(:print)
|
8
|
-
$stdout.stub(:puts)
|
9
|
-
end
|
10
|
-
|
11
|
-
describe "#add" do
|
12
|
-
before do
|
13
|
-
FileUtils.mkdir_p("/projects/foo")
|
14
|
-
Dir.chdir("/projects/foo")
|
15
|
-
@app = Shelly::App.new
|
16
|
-
@app.stub(:add_git_remote)
|
17
|
-
@app.stub(:create)
|
18
|
-
@app.stub(:generate_cloudfile).and_return("Example Cloudfile")
|
19
|
-
@app.stub(:open_billing_page)
|
20
|
-
@app.stub(:remote_exists?).and_return(false)
|
21
|
-
Shelly::App.stub(:inside_git_repository?).and_return(true)
|
22
|
-
Shelly::App.stub(:new).and_return(@app)
|
23
|
-
end
|
24
|
-
|
25
|
-
it "should exit with message if command run outside git repository" do
|
26
|
-
Shelly::App.stub(:inside_git_repository?).and_return(false)
|
27
|
-
$stdout.should_receive(:puts).with("Must be run inside your project git repository")
|
28
|
-
lambda {
|
29
|
-
fake_stdin(["staging", "", ""]) do
|
30
|
-
@apps.add
|
31
|
-
end
|
32
|
-
}.should raise_error(SystemExit)
|
33
|
-
end
|
34
|
-
|
35
|
-
it "should ask user how he will use application" do
|
36
|
-
$stdout.should_receive(:print).with("How will you use this system (production - default,staging): ")
|
37
|
-
@app.should_receive(:purpose=).with("staging")
|
38
|
-
fake_stdin(["staging", "", ""]) do
|
39
|
-
@apps.add
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
context "when user provided empty purpose" do
|
44
|
-
it "should use 'production' as default" do
|
45
|
-
$stdout.should_receive(:print).with("How will you use this system (production - default,staging): ")
|
46
|
-
@app.should_receive(:purpose=).with("production")
|
47
|
-
fake_stdin(["", "", ""]) do
|
48
|
-
@apps.add
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
it "should use code name provided by user" do
|
54
|
-
$stdout.should_receive(:print).with("How will you use this system (production - default,staging): ")
|
55
|
-
$stdout.should_receive(:print).with("Application code name (foo-staging - default): ")
|
56
|
-
@app.should_receive(:code_name=).with("mycodename")
|
57
|
-
fake_stdin(["staging", "mycodename", ""]) do
|
58
|
-
@apps.add
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
context "when user provided empty code name" do
|
63
|
-
it "should use 'current_dirname-purpose' as default" do
|
64
|
-
$stdout.should_receive(:print).with("How will you use this system (production - default,staging): ")
|
65
|
-
$stdout.should_receive(:print).with("Application code name (foo-staging - default): ")
|
66
|
-
fake_stdin(["staging", "", ""]) do
|
67
|
-
@apps.add
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
it "should use database provided by user (separated by comma or space)" do
|
73
|
-
$stdout.should_receive(:print).with("Which database do you want to use postgresql, mongodb, redis, none (postgresql - default): ")
|
74
|
-
@app.should_receive(:databases=).with(["postgresql", "mongodb", "redis"])
|
75
|
-
fake_stdin(["staging", "", "postgresql,mongodb redis"]) do
|
76
|
-
@apps.add
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
it "should ask again for databases if unsupported kind typed" do
|
81
|
-
$stdout.should_receive(:print).with("Which database do you want to use postgresql, mongodb, redis, none (postgresql - default): ")
|
82
|
-
$stdout.should_receive(:print).with("Unknown database kind. Supported are: postgresql, mongodb, redis, none: ")
|
83
|
-
fake_stdin(["staging", "", "postgresql,doesnt-exist", "none"]) do
|
84
|
-
@apps.add
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
context "when user provided empty database" do
|
89
|
-
it "should use 'postgresql' database as default" do
|
90
|
-
@app.should_receive(:databases=).with(["postgresql"])
|
91
|
-
fake_stdin(["staging", "", ""]) do
|
92
|
-
@apps.add
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
it "should create the app on shelly cloud" do
|
98
|
-
@app.should_receive(:create)
|
99
|
-
fake_stdin(["", "", ""]) do
|
100
|
-
@apps.add
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
it "should display validation errors if they are any" do
|
105
|
-
response = {"message" => "Validation Failed", "errors" => [["code_name", "has been already taken"]]}
|
106
|
-
exception = Shelly::Client::APIError.new(response)
|
107
|
-
@app.should_receive(:create).and_raise(exception)
|
108
|
-
$stdout.should_receive(:puts).with("code_name has been already taken")
|
109
|
-
lambda {
|
110
|
-
fake_stdin(["", "", ""]) do
|
111
|
-
@apps.add
|
112
|
-
end
|
113
|
-
}.should raise_error(SystemExit)
|
114
|
-
end
|
115
|
-
|
116
|
-
context "git remote doesn't exist" do
|
117
|
-
it "should add git remote" do
|
118
|
-
$stdout.should_receive(:puts).with("\e[32mAdding remote staging git@git.shellycloud.com:foooo.git\e[0m")
|
119
|
-
@app.should_receive(:add_git_remote)
|
120
|
-
fake_stdin(["staging", "foooo", ""]) do
|
121
|
-
@apps.add
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
context "git remote exist" do
|
127
|
-
before do
|
128
|
-
@app.stub(:remote_exists?).and_return(true)
|
129
|
-
end
|
130
|
-
|
131
|
-
it "should ask user if he wants to overwrite existing git remote" do
|
132
|
-
$stdout.should_receive(:puts).with("Remote staging already exists")
|
133
|
-
$stdout.should_receive(:print).with("Would you like to overwrite remote staging with git@git.shellycloud.com:foooo.git (Y/N)?: ")
|
134
|
-
fake_stdin(["staging", "foooo", "", "y"]) do
|
135
|
-
@apps.add
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
it "should overwrite existing git remote on 'yes' from user" do
|
140
|
-
@app.should_receive(:add_git_remote).with(true)
|
141
|
-
fake_stdin(["staging", "foooo", "", "y"]) do
|
142
|
-
@apps.add
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
it "should not overwrite existing git remote on 'no' from user" do
|
147
|
-
@app.should_not_receive(:add_git_remote).with(true)
|
148
|
-
fake_stdin(["staging", "foooo", "", "n"]) do
|
149
|
-
@apps.add
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
it "should create Cloudfile" do
|
155
|
-
File.exists?("/projects/foo/Cloudfile").should be_false
|
156
|
-
fake_stdin(["staging", "foooo", ""]) do
|
157
|
-
@apps.add
|
158
|
-
end
|
159
|
-
File.read("/projects/foo/Cloudfile").should == "Example Cloudfile"
|
160
|
-
end
|
161
|
-
|
162
|
-
it "should browser window with link to edit billing information" do
|
163
|
-
$stdout.should_receive(:puts).with("\e[32mProvide billing details. Opening browser...\e[0m")
|
164
|
-
@app.should_receive(:open_billing_page)
|
165
|
-
fake_stdin(["staging", "foooo", ""]) do
|
166
|
-
@apps.add
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
it "should display info about adding Cloudfile to repository" do
|
171
|
-
$stdout.should_receive(:puts).with("\e[32mProject is now configured for use with Shell Cloud:\e[0m")
|
172
|
-
$stdout.should_receive(:puts).with("\e[32mYou can review changes using\e[0m")
|
173
|
-
$stdout.should_receive(:puts).with(" git diff")
|
174
|
-
fake_stdin(["staging", "foooo", "none"]) do
|
175
|
-
@apps.add
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
it "should display info on how to deploy to ShellyCloud" do
|
180
|
-
$stdout.should_receive(:puts).with("\e[32mWhen you make sure all settings are correct please issue following commands:\e[0m")
|
181
|
-
$stdout.should_receive(:puts).with(" git add .")
|
182
|
-
$stdout.should_receive(:puts).with(' git commit -m "Application added to Shelly Cloud"')
|
183
|
-
$stdout.should_receive(:puts).with(" git push")
|
184
|
-
$stdout.should_receive(:puts).with("\e[32mDeploy to staging using:\e[0m")
|
185
|
-
$stdout.should_receive(:puts).with(" git push staging master")
|
186
|
-
fake_stdin(["staging", "foooo", "none"]) do
|
187
|
-
@apps.add
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|