shelly 0.0.37 → 0.0.38
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.rb +4 -0
- data/lib/shelly/app.rb +14 -7
- data/lib/shelly/cli/backup.rb +3 -3
- data/lib/shelly/cli/command.rb +2 -0
- data/lib/shelly/cli/config.rb +8 -15
- data/lib/shelly/cli/deploys.rb +3 -3
- data/lib/shelly/cli/main.rb +7 -15
- data/lib/shelly/cli/runner.rb +2 -2
- data/lib/shelly/cli/user.rb +5 -5
- data/lib/shelly/client.rb +4 -4
- data/lib/shelly/helpers.rb +8 -1
- data/lib/shelly/version.rb +1 -1
- data/lib/thor/thor.rb +28 -0
- data/spec/helpers.rb +4 -0
- data/spec/shelly/app_spec.rb +24 -7
- data/spec/shelly/cli/backup_spec.rb +20 -17
- data/spec/shelly/cli/config_spec.rb +37 -36
- data/spec/shelly/cli/deploys_spec.rb +14 -11
- data/spec/shelly/cli/main_spec.rb +85 -107
- data/spec/shelly/cli/runner_spec.rb +9 -1
- data/spec/shelly/cli/user_spec.rb +25 -12
- data/spec/shelly/client_spec.rb +7 -6
- data/spec/shelly/cloudfile_spec.rb +11 -0
- metadata +151 -158
data/lib/shelly.rb
CHANGED
data/lib/shelly/app.rb
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
require 'erb'
|
2
2
|
require 'launchy'
|
3
|
+
require "shelly/backup"
|
3
4
|
|
4
5
|
module Shelly
|
5
6
|
class App < Model
|
6
7
|
DATABASE_KINDS = %w(postgresql mongodb redis none)
|
7
8
|
|
8
9
|
attr_accessor :code_name, :databases, :ruby_version, :environment,
|
9
|
-
:git_url, :domains
|
10
|
-
|
11
|
-
autoload :Backup, "shelly/backup"
|
10
|
+
:git_url, :domains, :web_server_ip, :mail_server_ip
|
12
11
|
|
13
12
|
def initialize(code_name = nil)
|
14
13
|
self.code_name = code_name
|
@@ -99,10 +98,6 @@ module Shelly
|
|
99
98
|
File.basename(Dir.pwd)
|
100
99
|
end
|
101
100
|
|
102
|
-
def ips
|
103
|
-
shelly.app_ips(code_name)
|
104
|
-
end
|
105
|
-
|
106
101
|
def users
|
107
102
|
shelly.app_users(code_name)
|
108
103
|
end
|
@@ -135,6 +130,18 @@ module Shelly
|
|
135
130
|
shelly.app_delete_config(code_name, path)
|
136
131
|
end
|
137
132
|
|
133
|
+
def attributes
|
134
|
+
@attributes ||= shelly.app(code_name)
|
135
|
+
end
|
136
|
+
|
137
|
+
def web_server_ip
|
138
|
+
attributes["web_server_ip"]
|
139
|
+
end
|
140
|
+
|
141
|
+
def mail_server_ip
|
142
|
+
attributes["mail_server_ip"]
|
143
|
+
end
|
144
|
+
|
138
145
|
def open_billing_page
|
139
146
|
url = "#{shelly.shellyapp_url}/login?api_key=#{current_user.token}&return_to=/apps/#{code_name}/edit_billing"
|
140
147
|
Launchy.open(url)
|
data/lib/shelly/cli/backup.rb
CHANGED
@@ -8,12 +8,13 @@ module Shelly
|
|
8
8
|
namespace :backup
|
9
9
|
include Helpers
|
10
10
|
|
11
|
+
before_hook :logged_in?, :only => [:list, :get, :create]
|
12
|
+
before_hook :cloudfile_present?, :only => [:list]
|
13
|
+
|
11
14
|
desc "list", "List database backups"
|
12
15
|
method_option :cloud, :type => :string, :aliases => "-c",
|
13
16
|
:desc => "Specify which cloud to list backups for"
|
14
17
|
def list
|
15
|
-
logged_in?
|
16
|
-
say_error "No Cloudfile found" unless Cloudfile.present?
|
17
18
|
multiple_clouds(options[:cloud], "backup list", "Select cloud to view database backups for using:")
|
18
19
|
backups = @app.database_backups
|
19
20
|
if backups.present?
|
@@ -60,7 +61,6 @@ module Shelly
|
|
60
61
|
method_option :cloud, :type => :string, :aliases => "-c",
|
61
62
|
:desc => "Specify which cloud to create database snapshot for"
|
62
63
|
def create(kind = nil)
|
63
|
-
logged_in?
|
64
64
|
multiple_clouds(options[:cloud], "backup create", "Select cloud to create snapshot of database")
|
65
65
|
@app.request_backup(kind)
|
66
66
|
say "Backup requested. It can take up to several minutes for" +
|
data/lib/shelly/cli/command.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "shelly"
|
2
2
|
require "thor"
|
3
|
+
require "thor/thor"
|
3
4
|
require "thor/group"
|
4
5
|
require "thor/options"
|
5
6
|
require "thor/arguments"
|
@@ -8,6 +9,7 @@ require "thor/basic"
|
|
8
9
|
module Shelly
|
9
10
|
module CLI
|
10
11
|
class Command < Thor
|
12
|
+
include Helpers
|
11
13
|
class_option :debug, :type => :boolean, :desc => "Show debug information"
|
12
14
|
end
|
13
15
|
end
|
data/lib/shelly/cli/config.rb
CHANGED
@@ -6,10 +6,11 @@ module Shelly
|
|
6
6
|
include Thor::Actions
|
7
7
|
include Helpers
|
8
8
|
|
9
|
+
before_hook :logged_in?, :only => [:list, :show, :create, :edit, :delete]
|
10
|
+
before_hook :cloudfile_present?, :only => [:list, :show, :create, :edit, :delete]
|
11
|
+
|
9
12
|
desc "list", "List configuration files"
|
10
13
|
def list
|
11
|
-
logged_in?
|
12
|
-
say_error "No Cloudfile found" unless Cloudfile.present?
|
13
14
|
cloudfile = Cloudfile.new
|
14
15
|
cloudfile.clouds.each do |cloud|
|
15
16
|
@app = App.new(cloud)
|
@@ -46,8 +47,6 @@ module Shelly
|
|
46
47
|
:desc => "Specify which cloud to show configuration file for"
|
47
48
|
desc "show PATH", "View configuration file"
|
48
49
|
def show(path = nil)
|
49
|
-
logged_in?
|
50
|
-
say_error "No Cloudfile found" unless Cloudfile.present?
|
51
50
|
say_error "No configuration file specified" unless path
|
52
51
|
multiple_clouds(options[:cloud], "show #{path}", "Specify cloud using:")
|
53
52
|
config = @app.config(path)
|
@@ -61,11 +60,9 @@ module Shelly
|
|
61
60
|
|
62
61
|
map "new" => :create
|
63
62
|
method_option :cloud, :type => :string, :aliases => "-c",
|
64
|
-
:desc => "Specify
|
63
|
+
:desc => "Specify which cloud to create configuration file for"
|
65
64
|
desc "create PATH", "Create configuration file"
|
66
65
|
def create(path = nil)
|
67
|
-
logged_in?
|
68
|
-
say_error "No Cloudfile found" unless Cloudfile.present?
|
69
66
|
say_error "No path specified" unless path
|
70
67
|
output = open_editor(path)
|
71
68
|
multiple_clouds(options[:cloud], "create #{path}", "Specify cloud using:")
|
@@ -84,11 +81,9 @@ module Shelly
|
|
84
81
|
|
85
82
|
map "update" => :edit
|
86
83
|
method_option :cloud, :type => :string, :aliases => "-c",
|
87
|
-
:desc => "Specify
|
84
|
+
:desc => "Specify which cloud to edit configuration file for"
|
88
85
|
desc "edit PATH", "Edit configuration file"
|
89
86
|
def edit(path = nil)
|
90
|
-
logged_in?
|
91
|
-
say_error "No Cloudfile found" unless Cloudfile.present?
|
92
87
|
say_error "No configuration file specified" unless path
|
93
88
|
multiple_clouds(options[:cloud], "edit #{path}", "Specify cloud using:")
|
94
89
|
config = @app.config(path)
|
@@ -107,15 +102,13 @@ module Shelly
|
|
107
102
|
end
|
108
103
|
|
109
104
|
method_option :cloud, :type => :string, :aliases => "-c",
|
110
|
-
:desc => "Specify for which cloud delete configuration file"
|
105
|
+
:desc => "Specify for which cloud to delete configuration file for"
|
111
106
|
desc "delete PATH", "Delete configuration file"
|
112
107
|
def delete(path = nil)
|
113
|
-
logged_in?
|
114
|
-
say_error "No Cloudfile found" unless Cloudfile.present?
|
115
108
|
say_error "No configuration file specified" unless path
|
116
109
|
multiple_clouds(options[:cloud], "delete #{path}", "Specify cloud using:")
|
117
|
-
answer =
|
118
|
-
if answer
|
110
|
+
answer = yes?("Are you sure you want to delete 'path' (yes/no): ")
|
111
|
+
if answer
|
119
112
|
@app.delete_config(path)
|
120
113
|
say "File deleted, redeploy your cloud to make changes", :green
|
121
114
|
else
|
data/lib/shelly/cli/deploys.rb
CHANGED
@@ -7,12 +7,13 @@ module Shelly
|
|
7
7
|
namespace :deploys
|
8
8
|
include Helpers
|
9
9
|
|
10
|
+
before_hook :logged_in?, :only => [:list, :show]
|
11
|
+
before_hook :cloudfile_present?, :only => [:list, :show]
|
12
|
+
|
10
13
|
desc "list", "Lists deploy logs"
|
11
14
|
method_option :cloud, :type => :string, :aliases => "-c",
|
12
15
|
:desc => "Specify which cloud to show deploy logs for"
|
13
16
|
def list
|
14
|
-
logged_in?
|
15
|
-
say_error "No Cloudfile found" unless Cloudfile.present?
|
16
17
|
multiple_clouds(options[:cloud], "deploys list", "Select cloud to view deploy logs using:")
|
17
18
|
logs = @app.deploy_logs
|
18
19
|
unless logs.empty?
|
@@ -35,7 +36,6 @@ module Shelly
|
|
35
36
|
method_option :cloud, :type => :string, :aliases => "-c",
|
36
37
|
:desc => "Specify which cloud to show deploy logs for"
|
37
38
|
def show(log = nil)
|
38
|
-
say_error "No Cloudfile found" unless Cloudfile.present?
|
39
39
|
specify_log(log)
|
40
40
|
multiple_clouds(options[:cloud], "deploys show #{log}", "Select log and cloud to view deploy logs using:")
|
41
41
|
content = @app.deploy_log(log)
|
data/lib/shelly/cli/main.rb
CHANGED
@@ -8,13 +8,17 @@ module Shelly
|
|
8
8
|
module CLI
|
9
9
|
class Main < Command
|
10
10
|
include Thor::Actions
|
11
|
-
|
11
|
+
|
12
12
|
register(User, "user", "user <command>", "Manages users using this cloud")
|
13
13
|
register(Backup, "backup", "backup <command>", "Manages database backups from this cloud")
|
14
14
|
register(Deploys, "deploys", "deploys <command>", "View cloud deploy logs")
|
15
15
|
register(Config, "config", "config <command>", "Manages cloud configuration files")
|
16
16
|
check_unknown_options!
|
17
17
|
|
18
|
+
before_hook :logged_in?, :only => [:add, :list, :start, :stop, :logs, :delete]
|
19
|
+
before_hook :inside_git_repository?, :only => [:add, :ip]
|
20
|
+
before_hook :cloudfile_present?, :only => [:logs, :stop, :start, :ip]
|
21
|
+
|
18
22
|
map %w(-v --version) => :version
|
19
23
|
desc "version", "Displays shelly version"
|
20
24
|
def version
|
@@ -89,7 +93,6 @@ module Shelly
|
|
89
93
|
:desc => "Array of your domains"
|
90
94
|
desc "add", "Adds new cloud to Shelly Cloud"
|
91
95
|
def add
|
92
|
-
say_error "Must be run inside your project git repository" unless App.inside_git_repository?
|
93
96
|
check_options(options)
|
94
97
|
@app = Shelly::App.new
|
95
98
|
@app.code_name = options["code-name"] || ask_for_code_name
|
@@ -121,7 +124,6 @@ module Shelly
|
|
121
124
|
desc "list", "Lists all your clouds"
|
122
125
|
def list
|
123
126
|
user = Shelly::User.new
|
124
|
-
user.token
|
125
127
|
apps = user.apps
|
126
128
|
unless apps.empty?
|
127
129
|
say "You have following clouds available:", :green
|
@@ -141,16 +143,14 @@ module Shelly
|
|
141
143
|
|
142
144
|
desc "ip", "Lists clouds IP's"
|
143
145
|
def ip
|
144
|
-
say_error "Must be run inside your project git repository" unless App.inside_git_repository?
|
145
146
|
say_error "No Cloudfile found" unless Cloudfile.present?
|
146
147
|
@cloudfile = Cloudfile.new
|
147
148
|
@cloudfile.clouds.each do |cloud|
|
148
149
|
begin
|
149
150
|
@app = App.new(cloud)
|
150
151
|
say "Cloud #{cloud}:", :green
|
151
|
-
|
152
|
-
print_wrapped "
|
153
|
-
print_wrapped "Mail server IP: #{ips['mail_server_ip']}", :ident => 2
|
152
|
+
print_wrapped "Web server IP: #{@app.web_server_ip}", :ident => 2
|
153
|
+
print_wrapped "Mail server IP: #{@app.mail_server_ip}", :ident => 2
|
154
154
|
rescue Client::APIError => e
|
155
155
|
if e.unauthorized?
|
156
156
|
say_error "You have no access to '#{cloud}' cloud defined in Cloudfile", :with_exit => false
|
@@ -165,8 +165,6 @@ module Shelly
|
|
165
165
|
method_option :cloud, :type => :string, :aliases => "-c",
|
166
166
|
:desc => "Specify which cloud to start"
|
167
167
|
def start
|
168
|
-
logged_in?
|
169
|
-
say_error "No Cloudfile found" unless Cloudfile.present?
|
170
168
|
multiple_clouds(options[:cloud], "start", "Select cloud to start using:")
|
171
169
|
@app.start
|
172
170
|
say "Starting cloud #{@app.code_name}. Check status with:", :green
|
@@ -201,8 +199,6 @@ module Shelly
|
|
201
199
|
method_option :cloud, :type => :string, :aliases => "-c",
|
202
200
|
:desc => "Specify which cloud to stop"
|
203
201
|
def stop
|
204
|
-
logged_in?
|
205
|
-
say_error "No Cloudfile found" unless Cloudfile.present?
|
206
202
|
multiple_clouds(options[:cloud], "stop", "Select cloud to stop using:")
|
207
203
|
@app.stop
|
208
204
|
say "Cloud '#{@app.code_name}' stopped"
|
@@ -216,8 +212,6 @@ module Shelly
|
|
216
212
|
method_option :cloud, :type => :string, :aliases => "-c",
|
217
213
|
:desc => "Specify which cloud to delete"
|
218
214
|
def delete
|
219
|
-
user = Shelly::User.new
|
220
|
-
user.token
|
221
215
|
multiple_clouds(options[:cloud], "delete", "Select cloud to delete using:")
|
222
216
|
say "You are about to delete application: #{@app.code_name}."
|
223
217
|
say "Press Control-C at any moment to cancel."
|
@@ -244,8 +238,6 @@ module Shelly
|
|
244
238
|
:desc => "Specify which cloud to show logs for"
|
245
239
|
def logs
|
246
240
|
cloud = options[:cloud]
|
247
|
-
logged_in?
|
248
|
-
say_error "No Cloudfile found" unless Cloudfile.present?
|
249
241
|
multiple_clouds(cloud, "logs", "Select which to show logs for using:")
|
250
242
|
begin
|
251
243
|
logs = @app.application_logs
|
data/lib/shelly/cli/runner.rb
CHANGED
@@ -6,13 +6,13 @@ module Shelly
|
|
6
6
|
include Helpers
|
7
7
|
attr_accessor :args
|
8
8
|
|
9
|
-
def initialize(args)
|
9
|
+
def initialize(args = [])
|
10
10
|
super()
|
11
11
|
@args = args
|
12
12
|
end
|
13
13
|
|
14
14
|
def debug?
|
15
|
-
args.include?("--debug")
|
15
|
+
args.include?("--debug") || ENV['SHELLY_DEBUG'] == "true"
|
16
16
|
end
|
17
17
|
|
18
18
|
def start
|
data/lib/shelly/cli/user.rb
CHANGED
@@ -6,10 +6,12 @@ module Shelly
|
|
6
6
|
namespace :user
|
7
7
|
include Helpers
|
8
8
|
|
9
|
+
before_hook :logged_in?, :only => [:list, :add]
|
10
|
+
before_hook :inside_git_repository?, :only => [:list, :add]
|
11
|
+
before_hook :cloudfile_present?, :only => [:list, :add]
|
12
|
+
|
9
13
|
desc "list", "List users with access to clouds defined in Cloudfile"
|
10
14
|
def list
|
11
|
-
say_error "Must be run inside your project git repository" unless App.inside_git_repository?
|
12
|
-
say_error "No Cloudfile found" unless Cloudfile.present?
|
13
15
|
@cloudfile = Cloudfile.new
|
14
16
|
@cloudfile.clouds.each do |cloud|
|
15
17
|
begin
|
@@ -28,8 +30,6 @@ module Shelly
|
|
28
30
|
|
29
31
|
desc "add [EMAIL]", "Add new developer to clouds defined in Cloudfile"
|
30
32
|
def add(email = nil)
|
31
|
-
say_error "Must be run inside your project git repository" unless App.inside_git_repository?
|
32
|
-
say_error "No Cloudfile found" unless Cloudfile.present?
|
33
33
|
@cloudfile = Cloudfile.new
|
34
34
|
@user = Shelly::User.new
|
35
35
|
user_email = email || ask_for_email({:guess_email => false})
|
@@ -59,4 +59,4 @@ module Shelly
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
end
|
62
|
-
end
|
62
|
+
end
|
data/lib/shelly/client.rb
CHANGED
@@ -115,6 +115,10 @@ module Shelly
|
|
115
115
|
def apps
|
116
116
|
get("/apps")
|
117
117
|
end
|
118
|
+
|
119
|
+
def app(code_name)
|
120
|
+
get("/apps/#{code_name}")
|
121
|
+
end
|
118
122
|
|
119
123
|
def deploy_logs(cloud)
|
120
124
|
get("/apps/#{cloud}/deploys")
|
@@ -148,10 +152,6 @@ module Shelly
|
|
148
152
|
get("/apps/#{cloud}/users")
|
149
153
|
end
|
150
154
|
|
151
|
-
def app_ips(cloud)
|
152
|
-
get("/apps/#{cloud}/ips")
|
153
|
-
end
|
154
|
-
|
155
155
|
def post(path, params = {})
|
156
156
|
request(path, :post, params)
|
157
157
|
end
|
data/lib/shelly/helpers.rb
CHANGED
@@ -45,6 +45,14 @@ module Shelly
|
|
45
45
|
exit 1 unless delete_application == "yes"
|
46
46
|
end
|
47
47
|
|
48
|
+
def inside_git_repository?
|
49
|
+
say_error "Must be run inside your project git repository" unless App.inside_git_repository?
|
50
|
+
end
|
51
|
+
|
52
|
+
def cloudfile_present?
|
53
|
+
say_error "No Cloudfile found" unless Cloudfile.present?
|
54
|
+
end
|
55
|
+
|
48
56
|
def logged_in?
|
49
57
|
user = Shelly::User.new
|
50
58
|
user.token
|
@@ -74,4 +82,3 @@ module Shelly
|
|
74
82
|
|
75
83
|
end
|
76
84
|
end
|
77
|
-
|
data/lib/shelly/version.rb
CHANGED
data/lib/thor/thor.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
class Thor
|
2
|
+
class << self
|
3
|
+
def before_hook(method, options = {})
|
4
|
+
@hook = {} unless @hook
|
5
|
+
@hook[method] = options
|
6
|
+
end
|
7
|
+
|
8
|
+
def send(*args)
|
9
|
+
if args.first == :dispatch
|
10
|
+
running_task = args[2].first
|
11
|
+
@hook.each do |method, options|
|
12
|
+
if options[:only].include?(running_task.to_sym)
|
13
|
+
new.send(method)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
def start(given_args=ARGV, config={})
|
21
|
+
config[:shell] ||= Thor::Base.shell.new
|
22
|
+
send(:dispatch, nil, given_args.dup, nil, config)
|
23
|
+
rescue Thor::Error => e
|
24
|
+
ENV["THOR_DEBUG"] == "1" ? (raise e) : config[:shell].error(e.message)
|
25
|
+
exit(1) if exit_on_failure?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/spec/helpers.rb
CHANGED
data/spec/shelly/app_spec.rb
CHANGED
@@ -24,13 +24,6 @@ describe Shelly::App do
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
describe "#ips" do
|
28
|
-
it "should get app's ips" do
|
29
|
-
@client.should_receive(:app_ips).with("foo-staging")
|
30
|
-
@app.ips
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
27
|
describe "#add_git_remote" do
|
35
28
|
before do
|
36
29
|
@app.stub(:git_url).and_return("git@git.shellycloud.com:foo-staging.git")
|
@@ -64,6 +57,30 @@ describe Shelly::App do
|
|
64
57
|
@app.shelly_generated_configs
|
65
58
|
end
|
66
59
|
end
|
60
|
+
|
61
|
+
describe "#attributes" do
|
62
|
+
before do
|
63
|
+
@response = {"web_server_ip" => "192.0.2.1", "mail_server_ip" => "192.0.2.3"}
|
64
|
+
@client.stub(:app).and_return(@response)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should fetch app attributes from API and cache them" do
|
68
|
+
@client.should_receive(:app).with("foo-staging").exactly(:once).and_return(@response)
|
69
|
+
2.times { @app.attributes }
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "#web_server_ip" do
|
73
|
+
it "should return web server ip address" do
|
74
|
+
@app.web_server_ip.should == "192.0.2.1"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "#mail_server_ip" do
|
79
|
+
it "should return mail server ip address" do
|
80
|
+
@app.mail_server_ip.should == "192.0.2.3"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
67
84
|
|
68
85
|
describe "#generate_cloudfile" do
|
69
86
|
it "should return generated cloudfile" do
|