cf 0.1.5 → 0.6.0.rc1
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/LICENSE +1277 -30
- data/Rakefile +12 -1
- data/bin/cf +0 -3
- data/lib/cf.rb +6 -0
- data/lib/cf/cli.rb +389 -190
- data/lib/cf/cli/app/app.rb +45 -0
- data/lib/cf/cli/app/apps.rb +99 -0
- data/lib/cf/cli/app/base.rb +90 -0
- data/lib/cf/cli/app/crashes.rb +42 -0
- data/lib/cf/cli/app/delete.rb +95 -0
- data/lib/cf/cli/app/deprecated.rb +11 -0
- data/lib/cf/cli/app/env.rb +78 -0
- data/lib/cf/cli/app/files.rb +137 -0
- data/lib/cf/cli/app/health.rb +26 -0
- data/lib/cf/cli/app/instances.rb +53 -0
- data/lib/cf/cli/app/logs.rb +76 -0
- data/lib/cf/cli/app/push.rb +105 -0
- data/lib/cf/cli/app/push/create.rb +149 -0
- data/lib/cf/cli/app/push/interactions.rb +94 -0
- data/lib/cf/cli/app/push/sync.rb +64 -0
- data/lib/cf/cli/app/rename.rb +35 -0
- data/lib/cf/cli/app/restart.rb +20 -0
- data/lib/cf/cli/app/scale.rb +69 -0
- data/lib/cf/cli/app/start.rb +143 -0
- data/lib/cf/cli/app/stats.rb +67 -0
- data/lib/cf/cli/app/stop.rb +27 -0
- data/lib/cf/cli/domain/base.rb +8 -0
- data/lib/cf/cli/domain/domains.rb +40 -0
- data/lib/cf/cli/domain/map.rb +55 -0
- data/lib/cf/cli/domain/unmap.rb +56 -0
- data/lib/cf/cli/help.rb +15 -0
- data/lib/cf/cli/interactive.rb +105 -0
- data/lib/cf/cli/organization/base.rb +12 -0
- data/lib/cf/cli/organization/create.rb +32 -0
- data/lib/cf/cli/organization/delete.rb +73 -0
- data/lib/cf/cli/organization/org.rb +45 -0
- data/lib/cf/cli/organization/orgs.rb +35 -0
- data/lib/cf/cli/organization/rename.rb +36 -0
- data/lib/cf/cli/route/base.rb +8 -0
- data/lib/cf/cli/route/map.rb +70 -0
- data/lib/cf/cli/route/routes.rb +26 -0
- data/lib/cf/cli/route/unmap.rb +62 -0
- data/lib/cf/cli/service/base.rb +8 -0
- data/lib/cf/cli/service/bind.rb +44 -0
- data/lib/cf/cli/service/create.rb +107 -0
- data/lib/cf/cli/service/delete.rb +82 -0
- data/lib/cf/cli/service/rename.rb +35 -0
- data/lib/cf/cli/service/service.rb +40 -0
- data/lib/cf/cli/service/services.rb +99 -0
- data/lib/cf/cli/service/unbind.rb +38 -0
- data/lib/cf/cli/space/base.rb +19 -0
- data/lib/cf/cli/space/create.rb +63 -0
- data/lib/cf/cli/space/delete.rb +95 -0
- data/lib/cf/cli/space/rename.rb +39 -0
- data/lib/cf/cli/space/space.rb +64 -0
- data/lib/cf/cli/space/spaces.rb +55 -0
- data/lib/cf/cli/space/switch.rb +16 -0
- data/lib/cf/cli/start/base.rb +93 -0
- data/lib/cf/cli/start/colors.rb +13 -0
- data/lib/cf/cli/start/info.rb +124 -0
- data/lib/cf/cli/start/login.rb +94 -0
- data/lib/cf/cli/start/logout.rb +17 -0
- data/lib/cf/cli/start/target.rb +69 -0
- data/lib/cf/cli/start/target_interactions.rb +37 -0
- data/lib/cf/cli/start/targets.rb +16 -0
- data/lib/cf/cli/user/base.rb +29 -0
- data/lib/cf/cli/user/create.rb +39 -0
- data/lib/cf/cli/user/passwd.rb +43 -0
- data/lib/cf/cli/user/register.rb +42 -0
- data/lib/cf/cli/user/users.rb +32 -0
- data/lib/cf/constants.rb +10 -7
- data/lib/cf/detect.rb +113 -48
- data/lib/cf/errors.rb +17 -0
- data/lib/cf/plugin.rb +28 -12
- data/lib/cf/spacing.rb +89 -0
- data/lib/cf/spec_helper.rb +1 -0
- data/lib/cf/test_support.rb +6 -0
- data/lib/cf/version.rb +1 -1
- data/spec/assets/hello-sinatra/Gemfile +3 -0
- data/spec/assets/hello-sinatra/Gemfile.lock +17 -0
- data/spec/assets/hello-sinatra/config.ru +3 -0
- data/spec/assets/hello-sinatra/fat-cat-makes-app-larger.png +0 -0
- data/spec/assets/hello-sinatra/main.rb +6 -0
- data/spec/assets/specker_runner/specker_runner_input.rb +6 -0
- data/spec/assets/specker_runner/specker_runner_pause.rb +5 -0
- data/spec/cf/cli/app/base_spec.rb +17 -0
- data/spec/cf/cli/app/delete_spec.rb +188 -0
- data/spec/cf/cli/app/instances_spec.rb +65 -0
- data/spec/cf/cli/app/push/create_spec.rb +661 -0
- data/spec/cf/cli/app/push_spec.rb +369 -0
- data/spec/cf/cli/app/rename_spec.rb +104 -0
- data/spec/cf/cli/app/scale_spec.rb +75 -0
- data/spec/cf/cli/app/start_spec.rb +208 -0
- data/spec/cf/cli/app/stats_spec.rb +68 -0
- data/spec/cf/cli/domain/map_spec.rb +130 -0
- data/spec/cf/cli/domain/unmap_spec.rb +69 -0
- data/spec/cf/cli/organization/orgs_spec.rb +108 -0
- data/spec/cf/cli/organization/rename_spec.rb +113 -0
- data/spec/cf/cli/route/map_spec.rb +121 -0
- data/spec/cf/cli/route/unmap_spec.rb +155 -0
- data/spec/cf/cli/service/bind_spec.rb +25 -0
- data/spec/cf/cli/service/delete_spec.rb +22 -0
- data/spec/cf/cli/service/rename_spec.rb +105 -0
- data/spec/cf/cli/service/service_spec.rb +23 -0
- data/spec/cf/cli/service/unbind_spec.rb +25 -0
- data/spec/cf/cli/space/create_spec.rb +93 -0
- data/spec/cf/cli/space/rename_spec.rb +102 -0
- data/spec/cf/cli/space/spaces_spec.rb +104 -0
- data/spec/cf/cli/space/switch_space_spec.rb +55 -0
- data/spec/cf/cli/start/info_spec.rb +160 -0
- data/spec/cf/cli/start/login_spec.rb +142 -0
- data/spec/cf/cli/start/logout_spec.rb +50 -0
- data/spec/cf/cli/start/target_spec.rb +123 -0
- data/spec/cf/cli/user/create_spec.rb +54 -0
- data/spec/cf/cli/user/passwd_spec.rb +102 -0
- data/spec/cf/cli/user/register_spec.rb +140 -0
- data/spec/cf/cli_spec.rb +442 -0
- data/spec/cf/detect_spec.rb +54 -0
- data/spec/console_app_specker/console_app_specker_matchers_spec.rb +173 -0
- data/spec/console_app_specker/specker_runner_spec.rb +167 -0
- data/spec/features/account_lifecycle_spec.rb +85 -0
- data/spec/features/login_spec.rb +66 -0
- data/spec/features/push_flow_spec.rb +125 -0
- data/spec/features/switching_targets_spec.rb +32 -0
- data/spec/spec_helper.rb +72 -0
- data/spec/support/command_helper.rb +81 -0
- data/spec/support/config_helper.rb +15 -0
- data/spec/support/console_app_specker_matchers.rb +86 -0
- data/spec/support/fake_home_dir.rb +55 -0
- data/spec/support/interact_helper.rb +29 -0
- data/spec/support/shared_examples/errors.rb +40 -0
- data/spec/support/shared_examples/input.rb +14 -0
- data/spec/support/specker_runner.rb +80 -0
- data/spec/support/tracking_expector.rb +71 -0
- metadata +427 -66
- data/lib/cf/cli/app.rb +0 -595
- data/lib/cf/cli/command.rb +0 -444
- data/lib/cf/cli/dots.rb +0 -133
- data/lib/cf/cli/service.rb +0 -112
- data/lib/cf/cli/user.rb +0 -71
data/lib/cf/cli/app.rb
DELETED
|
@@ -1,595 +0,0 @@
|
|
|
1
|
-
require "cf/cli/command"
|
|
2
|
-
require "cf/detect"
|
|
3
|
-
|
|
4
|
-
module CF
|
|
5
|
-
class App < Command
|
|
6
|
-
MEM_CHOICES = ["64M", "128M", "256M", "512M"]
|
|
7
|
-
|
|
8
|
-
desc "apps", "List your applications"
|
|
9
|
-
def apps
|
|
10
|
-
apps =
|
|
11
|
-
with_progress("Getting applications") do
|
|
12
|
-
client.apps
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
if apps.empty? and !simple_output?
|
|
16
|
-
puts ""
|
|
17
|
-
puts "No applications."
|
|
18
|
-
return
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
apps.each.with_index do |a, num|
|
|
22
|
-
display_app(a)
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
desc "health ...APPS", "Get application health"
|
|
27
|
-
def health(*names)
|
|
28
|
-
apps =
|
|
29
|
-
with_progress("Getting application health") do
|
|
30
|
-
names.collect do |n|
|
|
31
|
-
[n, app_status(client.app(n))]
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
apps.each do |name, status|
|
|
36
|
-
unless simple_output?
|
|
37
|
-
puts ""
|
|
38
|
-
print "#{c(name, :blue)}: "
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
puts status
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
desc "stop [APP]", "Stop an application"
|
|
46
|
-
def stop(name)
|
|
47
|
-
with_progress("Stopping #{c(name, :blue)}") do |s|
|
|
48
|
-
app = client.app(name)
|
|
49
|
-
|
|
50
|
-
unless app.exists?
|
|
51
|
-
s.fail do
|
|
52
|
-
err "Unknown application."
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
if app.stopped?
|
|
57
|
-
s.skip do
|
|
58
|
-
err "Application is not running."
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
app.stop!
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
desc "start [APP]", "Start an application"
|
|
67
|
-
flag(:debug_mode)
|
|
68
|
-
def start(name)
|
|
69
|
-
app = client.app(name)
|
|
70
|
-
|
|
71
|
-
unless app.exists?
|
|
72
|
-
err "Unknown application."
|
|
73
|
-
return
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
switch_mode(app, input(:debug_mode))
|
|
77
|
-
|
|
78
|
-
with_progress("Starting #{c(name, :blue)}") do |s|
|
|
79
|
-
if app.running?
|
|
80
|
-
s.skip do
|
|
81
|
-
err "Already started."
|
|
82
|
-
return
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
app.start!
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
check_application(app)
|
|
90
|
-
|
|
91
|
-
if app.debug_mode && !simple_output?
|
|
92
|
-
puts ""
|
|
93
|
-
instances(name)
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
desc "restart [APP]", "Stop and start an application"
|
|
98
|
-
flag(:debug_mode)
|
|
99
|
-
def restart(name)
|
|
100
|
-
stop(name)
|
|
101
|
-
start(name)
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
desc "delete [APP]", "Delete an application"
|
|
105
|
-
flag(:really) { |name, color = :blue|
|
|
106
|
-
force? || ask("Really delete #{c(name, color)}?", :default => false)
|
|
107
|
-
}
|
|
108
|
-
flag(:name) { |names|
|
|
109
|
-
ask("Delete which application?", :choices => names)
|
|
110
|
-
}
|
|
111
|
-
flag(:all, :default => false)
|
|
112
|
-
def delete(name = nil)
|
|
113
|
-
if input(:all)
|
|
114
|
-
return unless input(:really, "ALL APPS", :red)
|
|
115
|
-
|
|
116
|
-
with_progress("Deleting all applications") do
|
|
117
|
-
client.apps.collect(&:delete!)
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
return
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
unless name
|
|
124
|
-
apps = client.apps
|
|
125
|
-
return err "No applications." if apps.empty?
|
|
126
|
-
|
|
127
|
-
name = input(:name, apps.collect(&:name))
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
return unless input(:really, name)
|
|
131
|
-
|
|
132
|
-
with_progress("Deleting #{c(name, :blue)}") do
|
|
133
|
-
client.app(name).delete!
|
|
134
|
-
end
|
|
135
|
-
ensure
|
|
136
|
-
forget(:really)
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
desc "instances [APP]", "List an app's instances"
|
|
140
|
-
def instances(name)
|
|
141
|
-
instances =
|
|
142
|
-
with_progress("Getting instances for #{c(name, :blue)}") do
|
|
143
|
-
client.app(name).instances
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
instances.each do |i|
|
|
147
|
-
if simple_output?
|
|
148
|
-
puts i.index
|
|
149
|
-
else
|
|
150
|
-
puts ""
|
|
151
|
-
display_instance(i)
|
|
152
|
-
end
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
desc "files [APP] [PATH]", "Examine an app's files"
|
|
157
|
-
def files(name, path = "/")
|
|
158
|
-
files =
|
|
159
|
-
with_progress("Getting file listing") do
|
|
160
|
-
client.app(name).files(*path.split("/"))
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
puts "" unless simple_output?
|
|
164
|
-
|
|
165
|
-
files.each do |file|
|
|
166
|
-
puts file
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
desc "file [APP] [PATH]", "Print out an app's file contents"
|
|
171
|
-
def file(name, path = "/")
|
|
172
|
-
file =
|
|
173
|
-
with_progress("Getting file contents") do
|
|
174
|
-
client.app(name).file(*path.split("/"))
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
puts "" unless simple_output?
|
|
178
|
-
|
|
179
|
-
print file
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
desc "logs [APP]", "Print out an app's logs"
|
|
183
|
-
flag(:instance, :type => :numeric, :default => 0)
|
|
184
|
-
def logs(name)
|
|
185
|
-
app = client.app(name)
|
|
186
|
-
unless app.exists?
|
|
187
|
-
err "Unknown application."
|
|
188
|
-
return
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
instances =
|
|
192
|
-
if input(:instance) == "all"
|
|
193
|
-
app.instances
|
|
194
|
-
else
|
|
195
|
-
app.instances.select { |i| i.index == input(:instance) }
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
if instances.empty?
|
|
199
|
-
if input(:instance) == "all"
|
|
200
|
-
err "No instances found."
|
|
201
|
-
else
|
|
202
|
-
err "Instance #{name} \##{input(:instance)} not found."
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
return
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
instances.each do |i|
|
|
209
|
-
logs =
|
|
210
|
-
with_progress(
|
|
211
|
-
"Getting logs for " +
|
|
212
|
-
c(name, :blue) + " " +
|
|
213
|
-
c("\##{i.index}", :yellow)) do
|
|
214
|
-
i.files("logs")
|
|
215
|
-
end
|
|
216
|
-
|
|
217
|
-
puts "" unless simple_output?
|
|
218
|
-
|
|
219
|
-
logs.each do |log|
|
|
220
|
-
body =
|
|
221
|
-
with_progress("Reading " + b(log.join("/"))) do
|
|
222
|
-
i.file(*log)
|
|
223
|
-
end
|
|
224
|
-
|
|
225
|
-
puts body
|
|
226
|
-
puts "" unless body.empty?
|
|
227
|
-
end
|
|
228
|
-
end
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
desc "push [NAME]", "Push an application, syncing changes if it exists"
|
|
232
|
-
flag(:name) { ask("Name") }
|
|
233
|
-
flag(:path) {
|
|
234
|
-
ask("Push from...", :default => ".")
|
|
235
|
-
}
|
|
236
|
-
flag(:url) { |name, target|
|
|
237
|
-
ask("URL", :default => "#{name}.#{target}")
|
|
238
|
-
}
|
|
239
|
-
flag(:memory) {
|
|
240
|
-
ask("Memory Limit",
|
|
241
|
-
:choices => MEM_CHOICES,
|
|
242
|
-
|
|
243
|
-
# TODO: base this on framework choice
|
|
244
|
-
:default => "64M")
|
|
245
|
-
}
|
|
246
|
-
flag(:instances) {
|
|
247
|
-
ask("Instances", :default => 1)
|
|
248
|
-
}
|
|
249
|
-
flag(:framework) { |choices, default|
|
|
250
|
-
ask("Framework", :choices => choices, :default => default)
|
|
251
|
-
}
|
|
252
|
-
flag(:runtime) { |choices|
|
|
253
|
-
ask("Runtime", :choices => choices)
|
|
254
|
-
}
|
|
255
|
-
flag(:start, :default => true)
|
|
256
|
-
flag(:restart, :default => true)
|
|
257
|
-
def push(name = nil)
|
|
258
|
-
path = File.expand_path(input(:path))
|
|
259
|
-
|
|
260
|
-
name ||= input(:name)
|
|
261
|
-
|
|
262
|
-
detector = Detector.new(client, path)
|
|
263
|
-
frameworks = detector.all_frameworks
|
|
264
|
-
detected, default = detector.frameworks
|
|
265
|
-
|
|
266
|
-
app = client.app(name)
|
|
267
|
-
|
|
268
|
-
if app.exists?
|
|
269
|
-
upload_app(app, path)
|
|
270
|
-
restart(app.name) if input(:restart)
|
|
271
|
-
return
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
app.total_instances = input(:instances)
|
|
275
|
-
|
|
276
|
-
domain = client.target.sub(/^https?:\/\/api\.(.+)\/?/, '\1')
|
|
277
|
-
app.urls = [input(:url, name, domain)]
|
|
278
|
-
|
|
279
|
-
framework = input(:framework, ["other"] + detected.keys, default)
|
|
280
|
-
if framework == "other"
|
|
281
|
-
forget(:framework)
|
|
282
|
-
framework = input(:framework, frameworks.keys)
|
|
283
|
-
end
|
|
284
|
-
|
|
285
|
-
framework_runtimes =
|
|
286
|
-
frameworks[framework]["runtimes"].collect do |k|
|
|
287
|
-
"#{k["name"]} (#{k["description"]})"
|
|
288
|
-
end
|
|
289
|
-
|
|
290
|
-
# TODO: include descriptions
|
|
291
|
-
runtime = input(:runtime, framework_runtimes).split.first
|
|
292
|
-
|
|
293
|
-
app.framework = framework
|
|
294
|
-
app.runtime = runtime
|
|
295
|
-
|
|
296
|
-
app.memory = megabytes(input(:memory))
|
|
297
|
-
|
|
298
|
-
with_progress("Creating #{c(name, :blue)}") do
|
|
299
|
-
app.create!
|
|
300
|
-
end
|
|
301
|
-
|
|
302
|
-
begin
|
|
303
|
-
upload_app(app, path)
|
|
304
|
-
rescue
|
|
305
|
-
err "Upload failed. Try again with 'vmc push'."
|
|
306
|
-
raise
|
|
307
|
-
end
|
|
308
|
-
|
|
309
|
-
start(name) if input(:start)
|
|
310
|
-
end
|
|
311
|
-
|
|
312
|
-
desc "update", "DEPRECATED", :hide => true
|
|
313
|
-
def update(*args)
|
|
314
|
-
err "The 'update' command is no longer used; use 'push' instead."
|
|
315
|
-
end
|
|
316
|
-
|
|
317
|
-
desc "stats [APP]", "Display application instance status"
|
|
318
|
-
def stats(name)
|
|
319
|
-
stats =
|
|
320
|
-
with_progress("Getting stats") do
|
|
321
|
-
client.app(name).stats
|
|
322
|
-
end
|
|
323
|
-
|
|
324
|
-
stats.sort_by { |k, _| k }.each do |idx, info|
|
|
325
|
-
stats = info["stats"]
|
|
326
|
-
usage = stats["usage"]
|
|
327
|
-
puts ""
|
|
328
|
-
puts "instance #{c("#" + idx, :blue)}:"
|
|
329
|
-
print " cpu: #{percentage(usage["cpu"])} of"
|
|
330
|
-
puts " #{b(stats["cores"])} cores"
|
|
331
|
-
puts " memory: #{usage(usage["mem"] * 1024, stats["mem_quota"])}"
|
|
332
|
-
puts " disk: #{usage(usage["disk"], stats["disk_quota"])}"
|
|
333
|
-
end
|
|
334
|
-
end
|
|
335
|
-
|
|
336
|
-
desc "scale [APP]", "Update the instances/memory limit for an application"
|
|
337
|
-
flag(:instances, :type => :numeric) { |default|
|
|
338
|
-
ask("Instances", :default => default)
|
|
339
|
-
}
|
|
340
|
-
flag(:memory) { |default|
|
|
341
|
-
ask("Memory Limit",
|
|
342
|
-
:default => human_size(default * 1024 * 1024, 0),
|
|
343
|
-
:choices => MEM_CHOICES)
|
|
344
|
-
}
|
|
345
|
-
def scale(name)
|
|
346
|
-
app = client.app(name)
|
|
347
|
-
|
|
348
|
-
instances = passed_value(:instances)
|
|
349
|
-
memory = passed_value(:memory)
|
|
350
|
-
|
|
351
|
-
unless instances || memory
|
|
352
|
-
instances = input(:instances, app.total_instances)
|
|
353
|
-
memory = input(:memory, app.memory)
|
|
354
|
-
end
|
|
355
|
-
|
|
356
|
-
with_progress("Scaling #{c(name, :blue)}") do
|
|
357
|
-
app.total_instances = instances.to_i if instances
|
|
358
|
-
app.memory = megabytes(memory) if memory
|
|
359
|
-
app.update!
|
|
360
|
-
end
|
|
361
|
-
end
|
|
362
|
-
|
|
363
|
-
desc "map NAME URL", "Add a URL mapping for an app"
|
|
364
|
-
def map(name, url)
|
|
365
|
-
simple = url.sub(/^https?:\/\/(.*)\/?/i, '\1')
|
|
366
|
-
|
|
367
|
-
with_progress("Updating #{c(name, :blue)}") do
|
|
368
|
-
app = client.app(name)
|
|
369
|
-
app.urls << simple
|
|
370
|
-
app.update!
|
|
371
|
-
end
|
|
372
|
-
end
|
|
373
|
-
|
|
374
|
-
desc "unmap NAME URL", "Remove a URL mapping from an app"
|
|
375
|
-
def unmap(name, url)
|
|
376
|
-
simple = url.sub(/^https?:\/\/(.*)\/?/i, '\1')
|
|
377
|
-
|
|
378
|
-
with_progress("Updating #{c(name, :blue)}") do |s|
|
|
379
|
-
app = client.app(name)
|
|
380
|
-
|
|
381
|
-
unless app.urls.delete(simple)
|
|
382
|
-
s.fail do
|
|
383
|
-
err "URL #{url} is not mapped to this application."
|
|
384
|
-
return
|
|
385
|
-
end
|
|
386
|
-
end
|
|
387
|
-
|
|
388
|
-
app.update!
|
|
389
|
-
end
|
|
390
|
-
end
|
|
391
|
-
|
|
392
|
-
class Env < Command
|
|
393
|
-
VALID_NAME = /^[a-zA-Za-z_][[:alnum:]_]*$/
|
|
394
|
-
|
|
395
|
-
desc "set [APP] [NAME] [VALUE]", "Set an environment variable"
|
|
396
|
-
def set(appname, name, value)
|
|
397
|
-
app = client.app(appname)
|
|
398
|
-
unless name =~ VALID_NAME
|
|
399
|
-
err "Invalid variable name; must match #{VALID_NAME.inspect}"
|
|
400
|
-
return
|
|
401
|
-
end
|
|
402
|
-
|
|
403
|
-
unless app.exists?
|
|
404
|
-
err "Unknown application."
|
|
405
|
-
return
|
|
406
|
-
end
|
|
407
|
-
|
|
408
|
-
with_progress("Updating #{c(app.name, :blue)}") do
|
|
409
|
-
app.update!("env" =>
|
|
410
|
-
app.env.reject { |v|
|
|
411
|
-
v.start_with?("#{name}=")
|
|
412
|
-
}.push("#{name}=#{value}"))
|
|
413
|
-
end
|
|
414
|
-
end
|
|
415
|
-
|
|
416
|
-
desc "unset [APP] [NAME]", "Remove an environment variable"
|
|
417
|
-
def unset(appname, name)
|
|
418
|
-
app = client.app(appname)
|
|
419
|
-
|
|
420
|
-
unless app.exists?
|
|
421
|
-
err "Unknown application."
|
|
422
|
-
return
|
|
423
|
-
end
|
|
424
|
-
|
|
425
|
-
with_progress("Updating #{c(app.name, :blue)}") do
|
|
426
|
-
app.update!("env" =>
|
|
427
|
-
app.env.reject { |v|
|
|
428
|
-
v.start_with?("#{name}=")
|
|
429
|
-
})
|
|
430
|
-
end
|
|
431
|
-
end
|
|
432
|
-
|
|
433
|
-
desc "list [APP]", "Show all environment variables set for an app"
|
|
434
|
-
def list(appname)
|
|
435
|
-
vars =
|
|
436
|
-
with_progress("Getting variables") do |s|
|
|
437
|
-
app = client.app(appname)
|
|
438
|
-
|
|
439
|
-
unless app.exists?
|
|
440
|
-
s.fail do
|
|
441
|
-
err "Unknown application."
|
|
442
|
-
return
|
|
443
|
-
end
|
|
444
|
-
end
|
|
445
|
-
|
|
446
|
-
app.env
|
|
447
|
-
end
|
|
448
|
-
|
|
449
|
-
puts "" unless simple_output?
|
|
450
|
-
|
|
451
|
-
vars.each do |pair|
|
|
452
|
-
name, val = pair.split("=", 2)
|
|
453
|
-
puts "#{c(name, :blue)}: #{val}"
|
|
454
|
-
end
|
|
455
|
-
end
|
|
456
|
-
end
|
|
457
|
-
|
|
458
|
-
desc "env SUBCOMMAND ...ARGS", "Manage application environment variables"
|
|
459
|
-
subcommand "env", Env
|
|
460
|
-
|
|
461
|
-
private
|
|
462
|
-
|
|
463
|
-
def upload_app(app, path)
|
|
464
|
-
with_progress("Uploading #{c(app.name, :blue)}") do
|
|
465
|
-
app.upload(path)
|
|
466
|
-
end
|
|
467
|
-
end
|
|
468
|
-
|
|
469
|
-
# set app debug mode, ensuring it's valid, and shutting it down
|
|
470
|
-
def switch_mode(app, mode)
|
|
471
|
-
mode = nil if mode == "none"
|
|
472
|
-
|
|
473
|
-
return false if app.debug_mode == mode
|
|
474
|
-
|
|
475
|
-
if mode.nil?
|
|
476
|
-
with_progress("Removing debug mode") do
|
|
477
|
-
app.debug_mode = nil
|
|
478
|
-
app.stop! if app.running?
|
|
479
|
-
end
|
|
480
|
-
|
|
481
|
-
return true
|
|
482
|
-
end
|
|
483
|
-
|
|
484
|
-
with_progress("Switching mode to #{c(mode, :blue)}") do |s|
|
|
485
|
-
runtimes = client.system_runtimes
|
|
486
|
-
modes = runtimes[app.runtime]["debug_modes"] || []
|
|
487
|
-
if modes.include?(mode)
|
|
488
|
-
app.debug_mode = mode
|
|
489
|
-
app.stop! if app.running?
|
|
490
|
-
true
|
|
491
|
-
else
|
|
492
|
-
s.fail do
|
|
493
|
-
err "Unknown mode '#{mode}'; available: #{modes.inspect}"
|
|
494
|
-
false
|
|
495
|
-
end
|
|
496
|
-
end
|
|
497
|
-
end
|
|
498
|
-
end
|
|
499
|
-
|
|
500
|
-
APP_CHECK_LIMIT = 60
|
|
501
|
-
|
|
502
|
-
def check_application(app)
|
|
503
|
-
with_progress("Checking #{c(app.name, :blue)}") do |s|
|
|
504
|
-
if app.debug_mode == "suspend"
|
|
505
|
-
s.skip do
|
|
506
|
-
puts "Application is in suspended debugging mode."
|
|
507
|
-
puts "It will wait for you to attach to it before starting."
|
|
508
|
-
end
|
|
509
|
-
end
|
|
510
|
-
|
|
511
|
-
seconds = 0
|
|
512
|
-
until app.healthy?
|
|
513
|
-
sleep 1
|
|
514
|
-
seconds += 1
|
|
515
|
-
if seconds == APP_CHECK_LIMIT
|
|
516
|
-
s.give_up do
|
|
517
|
-
err "Application failed to start."
|
|
518
|
-
# TODO: print logs
|
|
519
|
-
end
|
|
520
|
-
end
|
|
521
|
-
end
|
|
522
|
-
end
|
|
523
|
-
end
|
|
524
|
-
|
|
525
|
-
# choose the right color for app/instance state
|
|
526
|
-
def state_color(s)
|
|
527
|
-
case s
|
|
528
|
-
when "STARTING"
|
|
529
|
-
:blue
|
|
530
|
-
when "STARTED", "RUNNING"
|
|
531
|
-
:green
|
|
532
|
-
when "DOWN"
|
|
533
|
-
:red
|
|
534
|
-
when "FLAPPING"
|
|
535
|
-
:magenta
|
|
536
|
-
when "N/A"
|
|
537
|
-
:cyan
|
|
538
|
-
else
|
|
539
|
-
:yellow
|
|
540
|
-
end
|
|
541
|
-
end
|
|
542
|
-
|
|
543
|
-
def app_status(a)
|
|
544
|
-
health = a.health
|
|
545
|
-
|
|
546
|
-
if a.debug_mode == "suspend" && health == "0%"
|
|
547
|
-
c("suspended", :yellow)
|
|
548
|
-
else
|
|
549
|
-
c(health.downcase, state_color(health))
|
|
550
|
-
end
|
|
551
|
-
end
|
|
552
|
-
|
|
553
|
-
def display_app(a)
|
|
554
|
-
if simple_output?
|
|
555
|
-
puts a.name
|
|
556
|
-
return
|
|
557
|
-
end
|
|
558
|
-
|
|
559
|
-
puts ""
|
|
560
|
-
|
|
561
|
-
status = app_status(a)
|
|
562
|
-
|
|
563
|
-
print "#{c(a.name, :blue)}: #{status}"
|
|
564
|
-
|
|
565
|
-
unless a.total_instances == 1
|
|
566
|
-
print ", #{b(a.total_instances)} instances"
|
|
567
|
-
end
|
|
568
|
-
|
|
569
|
-
puts ""
|
|
570
|
-
|
|
571
|
-
unless a.urls.empty?
|
|
572
|
-
puts " urls: #{a.urls.collect { |u| b(u) }.join(", ")}"
|
|
573
|
-
end
|
|
574
|
-
|
|
575
|
-
unless a.services.empty?
|
|
576
|
-
puts " services: #{a.services.collect { |s| b(s) }.join(", ")}"
|
|
577
|
-
end
|
|
578
|
-
end
|
|
579
|
-
|
|
580
|
-
def display_instance(i)
|
|
581
|
-
print "instance #{c("\##{i.index}", :blue)}: "
|
|
582
|
-
puts "#{b(c(i.state.downcase, state_color(i.state)))} "
|
|
583
|
-
|
|
584
|
-
puts " started: #{c(i.since.strftime("%F %r"), :cyan)}"
|
|
585
|
-
|
|
586
|
-
if d = i.debugger
|
|
587
|
-
puts " debugger: port #{c(d["port"], :blue)} at #{c(d["ip"], :blue)}"
|
|
588
|
-
end
|
|
589
|
-
|
|
590
|
-
if c = i.console
|
|
591
|
-
puts " console: port #{b(c["port"])} at #{b(c["ip"])}"
|
|
592
|
-
end
|
|
593
|
-
end
|
|
594
|
-
end
|
|
595
|
-
end
|