af 0.3.22 → 0.5.0.beta.1
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 +14 -6
- data/LICENSE +1277 -24
- data/Rakefile +24 -87
- data/bin/af +7 -2
- data/lib/af/version.rb +3 -0
- data/lib/vmc.rb +7 -2
- data/lib/vmc/cli.rb +475 -0
- data/lib/vmc/cli/app/app.rb +45 -0
- data/lib/vmc/cli/app/apps.rb +105 -0
- data/lib/vmc/cli/app/base.rb +82 -0
- data/lib/vmc/cli/app/crashes.rb +46 -0
- data/lib/vmc/cli/app/delete.rb +95 -0
- data/lib/vmc/cli/app/deprecated.rb +11 -0
- data/lib/vmc/cli/app/env.rb +78 -0
- data/lib/vmc/cli/app/files.rb +137 -0
- data/lib/vmc/cli/app/health.rb +26 -0
- data/lib/vmc/cli/app/instances.rb +53 -0
- data/lib/vmc/cli/app/logs.rb +76 -0
- data/lib/vmc/cli/app/push.rb +107 -0
- data/lib/vmc/cli/app/push/create.rb +150 -0
- data/lib/vmc/cli/app/push/interactions.rb +100 -0
- data/lib/vmc/cli/app/push/sync.rb +64 -0
- data/lib/vmc/cli/app/rename.rb +39 -0
- data/lib/vmc/cli/app/restart.rb +20 -0
- data/lib/vmc/cli/app/scale.rb +71 -0
- data/lib/vmc/cli/app/start.rb +93 -0
- data/lib/vmc/cli/app/stats.rb +67 -0
- data/lib/vmc/cli/app/stop.rb +27 -0
- data/lib/vmc/cli/domain/base.rb +12 -0
- data/lib/vmc/cli/domain/domains.rb +40 -0
- data/lib/vmc/cli/domain/map.rb +55 -0
- data/lib/vmc/cli/domain/unmap.rb +56 -0
- data/lib/vmc/cli/help.rb +16 -0
- data/lib/vmc/cli/interactive.rb +105 -0
- data/lib/vmc/cli/organization/base.rb +14 -0
- data/lib/vmc/cli/organization/create.rb +32 -0
- data/lib/vmc/cli/organization/delete.rb +73 -0
- data/lib/vmc/cli/organization/org.rb +45 -0
- data/lib/vmc/cli/organization/orgs.rb +35 -0
- data/lib/vmc/cli/organization/rename.rb +36 -0
- data/lib/vmc/cli/route/base.rb +12 -0
- data/lib/vmc/cli/route/map.rb +80 -0
- data/lib/vmc/cli/route/routes.rb +26 -0
- data/lib/vmc/cli/route/unmap.rb +94 -0
- data/lib/vmc/cli/service/base.rb +8 -0
- data/lib/vmc/cli/service/bind.rb +44 -0
- data/lib/vmc/cli/service/create.rb +126 -0
- data/lib/vmc/cli/service/delete.rb +86 -0
- data/lib/vmc/cli/service/rename.rb +35 -0
- data/lib/vmc/cli/service/service.rb +42 -0
- data/lib/vmc/cli/service/services.rb +115 -0
- data/lib/vmc/cli/service/unbind.rb +38 -0
- data/lib/vmc/cli/space/base.rb +21 -0
- data/lib/vmc/cli/space/create.rb +56 -0
- data/lib/vmc/cli/space/delete.rb +95 -0
- data/lib/vmc/cli/space/rename.rb +39 -0
- data/lib/vmc/cli/space/space.rb +64 -0
- data/lib/vmc/cli/space/spaces.rb +55 -0
- data/lib/vmc/cli/space/take.rb +16 -0
- data/lib/vmc/cli/start/base.rb +80 -0
- data/lib/vmc/cli/start/colors.rb +13 -0
- data/lib/vmc/cli/start/info.rb +122 -0
- data/lib/vmc/cli/start/login.rb +92 -0
- data/lib/vmc/cli/start/logout.rb +13 -0
- data/lib/vmc/cli/start/target.rb +64 -0
- data/lib/vmc/cli/start/target_interactions.rb +37 -0
- data/lib/vmc/cli/start/targets.rb +16 -0
- data/lib/vmc/cli/user/base.rb +29 -0
- data/lib/vmc/cli/user/create.rb +39 -0
- data/lib/vmc/cli/user/delete.rb +25 -0
- data/lib/vmc/cli/user/passwd.rb +50 -0
- data/lib/vmc/cli/user/register.rb +42 -0
- data/lib/vmc/cli/user/users.rb +32 -0
- data/lib/vmc/constants.rb +13 -0
- data/lib/vmc/detect.rb +134 -0
- data/lib/vmc/errors.rb +17 -0
- data/lib/vmc/plugin.rb +56 -0
- data/lib/vmc/spacing.rb +89 -0
- data/lib/vmc/spec_helper.rb +1 -0
- data/lib/vmc/test_support.rb +4 -0
- data/lib/vmc/test_support/command_helper.rb +32 -0
- data/lib/vmc/test_support/common_input_examples.rb +14 -0
- data/lib/vmc/test_support/fake_home_dir.rb +16 -0
- data/lib/vmc/test_support/interact_helper.rb +29 -0
- data/lib/vmc/version.rb +3 -0
- data/spec/assets/hello-sinatra/Gemfile +3 -0
- data/spec/assets/hello-sinatra/main.rb +6 -0
- data/spec/features/new_user_flow_spec.rb +71 -0
- data/spec/spec_helper.rb +63 -0
- data/spec/vmc/cli/app/base_spec.rb +17 -0
- data/spec/vmc/cli/app/delete_spec.rb +188 -0
- data/spec/vmc/cli/app/instances_spec.rb +65 -0
- data/spec/vmc/cli/app/push/create_spec.rb +571 -0
- data/spec/vmc/cli/app/push_spec.rb +369 -0
- data/spec/vmc/cli/app/rename_spec.rb +104 -0
- data/spec/vmc/cli/app/scale_spec.rb +81 -0
- data/spec/vmc/cli/app/stats_spec.rb +62 -0
- data/spec/vmc/cli/domain/map_spec.rb +140 -0
- data/spec/vmc/cli/domain/unmap_spec.rb +73 -0
- data/spec/vmc/cli/organization/orgs_spec.rb +108 -0
- data/spec/vmc/cli/organization/rename_spec.rb +113 -0
- data/spec/vmc/cli/route/map_spec.rb +138 -0
- data/spec/vmc/cli/route/unmap_spec.rb +215 -0
- data/spec/vmc/cli/service/bind_spec.rb +25 -0
- data/spec/vmc/cli/service/delete_spec.rb +22 -0
- data/spec/vmc/cli/service/rename_spec.rb +105 -0
- data/spec/vmc/cli/service/service_spec.rb +23 -0
- data/spec/vmc/cli/service/unbind_spec.rb +25 -0
- data/spec/vmc/cli/space/rename_spec.rb +102 -0
- data/spec/vmc/cli/space/spaces_spec.rb +104 -0
- data/spec/vmc/cli/start/info_spec.rb +153 -0
- data/spec/vmc/cli/start/login_spec.rb +71 -0
- data/spec/vmc/cli/user/create_spec.rb +54 -0
- data/spec/vmc/cli/user/passwd_spec.rb +102 -0
- data/spec/vmc/cli/user/register_spec.rb +148 -0
- data/spec/vmc/cli_spec.rb +448 -0
- data/spec/vmc/detect_spec.rb +54 -0
- metadata +231 -124
- data/README.md +0 -155
- data/caldecott_helper/Gemfile +0 -10
- data/caldecott_helper/Gemfile.lock +0 -48
- data/caldecott_helper/server.rb +0 -43
- data/config/clients.yml +0 -17
- data/config/micro/offline.conf +0 -2
- data/config/micro/paths.yml +0 -22
- data/config/micro/refresh_ip.rb +0 -20
- data/lib/cli.rb +0 -48
- data/lib/cli/commands/admin.rb +0 -81
- data/lib/cli/commands/apps.rb +0 -1358
- data/lib/cli/commands/base.rb +0 -233
- data/lib/cli/commands/manifest.rb +0 -56
- data/lib/cli/commands/micro.rb +0 -115
- data/lib/cli/commands/misc.rb +0 -147
- data/lib/cli/commands/services.rb +0 -217
- data/lib/cli/commands/user.rb +0 -70
- data/lib/cli/config.rb +0 -176
- data/lib/cli/console_helper.rb +0 -163
- data/lib/cli/core_ext.rb +0 -122
- data/lib/cli/errors.rb +0 -19
- data/lib/cli/file_helper.rb +0 -123
- data/lib/cli/frameworks.rb +0 -265
- data/lib/cli/manifest_helper.rb +0 -316
- data/lib/cli/runner.rb +0 -633
- data/lib/cli/services_helper.rb +0 -104
- data/lib/cli/tunnel_helper.rb +0 -336
- data/lib/cli/usage.rb +0 -129
- data/lib/cli/version.rb +0 -7
- data/lib/cli/zip_util.rb +0 -102
- data/lib/vmc/client.rb +0 -574
- data/lib/vmc/const.rb +0 -27
- data/lib/vmc/micro.rb +0 -56
- data/lib/vmc/micro/switcher/base.rb +0 -97
- data/lib/vmc/micro/switcher/darwin.rb +0 -19
- data/lib/vmc/micro/switcher/dummy.rb +0 -15
- data/lib/vmc/micro/switcher/linux.rb +0 -16
- data/lib/vmc/micro/switcher/windows.rb +0 -31
- data/lib/vmc/micro/vmrun.rb +0 -158
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
require "thread"
|
|
2
|
+
require "vmc/cli/app/base"
|
|
3
|
+
|
|
4
|
+
module VMC::App
|
|
5
|
+
class Files < Base
|
|
6
|
+
desc "Print out an app's file contents"
|
|
7
|
+
group :apps, :info, :hidden => true
|
|
8
|
+
input :app, :desc => "Application to inspect the files of",
|
|
9
|
+
:argument => true, :from_given => by_name(:app)
|
|
10
|
+
input :path, :desc => "Path of file to read", :argument => :optional,
|
|
11
|
+
:default => "/"
|
|
12
|
+
def file
|
|
13
|
+
app = input[:app]
|
|
14
|
+
path = input[:path]
|
|
15
|
+
|
|
16
|
+
file =
|
|
17
|
+
with_progress("Getting file contents") do
|
|
18
|
+
app.file(*path.split("/"))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
if quiet?
|
|
22
|
+
print file
|
|
23
|
+
else
|
|
24
|
+
line
|
|
25
|
+
|
|
26
|
+
file.split("\n").each do |l|
|
|
27
|
+
line l
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
rescue CFoundry::NotFound
|
|
31
|
+
fail "Invalid path #{b(path)} for app #{b(app.name)}"
|
|
32
|
+
rescue CFoundry::FileError => e
|
|
33
|
+
fail e.description
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
desc "Examine an app's files"
|
|
37
|
+
group :apps, :info, :hidden => true
|
|
38
|
+
input :app, :desc => "Application to inspect the files of",
|
|
39
|
+
:argument => true, :from_given => by_name(:app)
|
|
40
|
+
input :path, :desc => "Path of directory to list", :argument => :optional,
|
|
41
|
+
:default => "/"
|
|
42
|
+
def files
|
|
43
|
+
app = input[:app]
|
|
44
|
+
path = input[:path]
|
|
45
|
+
|
|
46
|
+
if quiet?
|
|
47
|
+
files =
|
|
48
|
+
with_progress("Getting file listing") do
|
|
49
|
+
app.files(*path.split("/"))
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
files.each do |file|
|
|
53
|
+
line file.join("/")
|
|
54
|
+
end
|
|
55
|
+
else
|
|
56
|
+
invoke :file, :app => app, :path => path
|
|
57
|
+
end
|
|
58
|
+
rescue CFoundry::NotFound
|
|
59
|
+
fail "Invalid path #{b(path)} for app #{b(app.name)}"
|
|
60
|
+
rescue CFoundry::FileError => e
|
|
61
|
+
fail e.description
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
desc "Stream an app's file contents"
|
|
65
|
+
group :apps, :info, :hidden => true
|
|
66
|
+
input :app, :desc => "Application to inspect the files of",
|
|
67
|
+
:argument => true, :from_given => by_name(:app)
|
|
68
|
+
input :path, :desc => "Path of file to stream", :argument => :optional
|
|
69
|
+
def tail
|
|
70
|
+
app = input[:app]
|
|
71
|
+
|
|
72
|
+
lines = Queue.new
|
|
73
|
+
max_len = 0
|
|
74
|
+
|
|
75
|
+
if path = input[:path]
|
|
76
|
+
max_len = path.size
|
|
77
|
+
app.instances.each do |i|
|
|
78
|
+
Thread.new do
|
|
79
|
+
stream_path(lines, i, path.split("/"))
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
else
|
|
83
|
+
app.instances.each do |i|
|
|
84
|
+
i.files("logs").each do |path|
|
|
85
|
+
len = path.join("/").size
|
|
86
|
+
max_len = len if len > max_len
|
|
87
|
+
|
|
88
|
+
Thread.new do
|
|
89
|
+
stream_path(lines, i, path)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
while line = lines.pop
|
|
96
|
+
instance, path, log = line
|
|
97
|
+
|
|
98
|
+
unless log.end_with?("\n")
|
|
99
|
+
log += i("%") if color?
|
|
100
|
+
log += "\n"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
print "\##{c(instance.id, :instance)} "
|
|
104
|
+
print "#{c(path.join("/").ljust(max_len), :name)} "
|
|
105
|
+
print log
|
|
106
|
+
end
|
|
107
|
+
rescue CFoundry::NotFound
|
|
108
|
+
fail "Invalid path #{b(path)} for app #{b(app.name)}"
|
|
109
|
+
rescue CFoundry::FileError => e
|
|
110
|
+
fail e.description
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def stream_path(lines, instance, path)
|
|
114
|
+
if verbose?
|
|
115
|
+
lines << [instance, path, c("streaming...", :good) + "\n"]
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
instance.stream_file(*path) do |contents|
|
|
119
|
+
contents.each_line do |line|
|
|
120
|
+
lines << [instance, path, line]
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
lines << [instance, path, c("end of file", :bad) + "\n"]
|
|
125
|
+
rescue Timeout::Error
|
|
126
|
+
if verbose?
|
|
127
|
+
lines << [
|
|
128
|
+
instance,
|
|
129
|
+
path,
|
|
130
|
+
c("timed out; reconnecting...", :bad) + "\n"
|
|
131
|
+
]
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
retry
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require "vmc/cli/app/base"
|
|
2
|
+
|
|
3
|
+
module VMC::App
|
|
4
|
+
class Health < Base
|
|
5
|
+
desc "Get application health"
|
|
6
|
+
group :apps, :info, :hidden => true
|
|
7
|
+
input :apps, :desc => "Applications to start", :argument => :splat,
|
|
8
|
+
:singular => :app, :from_given => by_name(:app)
|
|
9
|
+
def health
|
|
10
|
+
apps = input[:apps]
|
|
11
|
+
fail "No applications given." if apps.empty?
|
|
12
|
+
|
|
13
|
+
health =
|
|
14
|
+
with_progress("Getting health status") do
|
|
15
|
+
apps.collect { |a| [a, app_status(a)] }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
line unless quiet?
|
|
19
|
+
|
|
20
|
+
spaced(health) do |app, status|
|
|
21
|
+
start_line "#{c(app.name, :name)}: " unless quiet?
|
|
22
|
+
puts status
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require "vmc/cli/app/base"
|
|
2
|
+
|
|
3
|
+
module VMC::App
|
|
4
|
+
class Instances < Base
|
|
5
|
+
desc "List an app's instances"
|
|
6
|
+
group :apps, :info, :hidden => true
|
|
7
|
+
input :apps, :desc => "Applications whose instances to list",
|
|
8
|
+
:argument => :splat, :singular => :app,
|
|
9
|
+
:from_given => by_name(:app)
|
|
10
|
+
def instances
|
|
11
|
+
apps = input[:apps]
|
|
12
|
+
fail "No applications given." if apps.empty?
|
|
13
|
+
|
|
14
|
+
spaced(apps) do |app|
|
|
15
|
+
instances =
|
|
16
|
+
with_progress("Getting instances for #{c(app.name, :name)}") do
|
|
17
|
+
app.instances
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
line unless quiet?
|
|
21
|
+
|
|
22
|
+
spaced(instances.sort { |a, b| a.id.to_i <=> b.id.to_i }) do |i|
|
|
23
|
+
if quiet?
|
|
24
|
+
line i.id
|
|
25
|
+
else
|
|
26
|
+
display_instance(i)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def display_instance(i)
|
|
35
|
+
start_line "instance #{c("\##{i.id}", :instance)}: "
|
|
36
|
+
puts "#{b(c(i.state.downcase, state_color(i.state)))}"
|
|
37
|
+
|
|
38
|
+
indented do
|
|
39
|
+
if s = i.since
|
|
40
|
+
line "started: #{c(s.strftime("%F %r"), :neutral)}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
if d = i.debugger
|
|
44
|
+
line "debugger: port #{b(d[:port])} at #{b(d[:ip])}"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
if c = i.console
|
|
48
|
+
line "console: port #{b(c[:port])} at #{b(c[:ip])}"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
require "vmc/cli/app/base"
|
|
2
|
+
|
|
3
|
+
module VMC::App
|
|
4
|
+
class Logs < Base
|
|
5
|
+
desc "Print out an app's logs"
|
|
6
|
+
group :apps, :info, :hidden => true
|
|
7
|
+
input :app, :desc => "Application to get the logs of", :argument => true,
|
|
8
|
+
:from_given => by_name(:app)
|
|
9
|
+
input :instance, :desc => "Instance of application to get the logs of",
|
|
10
|
+
:default => "0"
|
|
11
|
+
input :all, :desc => "Get logs for every instance", :default => false
|
|
12
|
+
def logs
|
|
13
|
+
app = input[:app]
|
|
14
|
+
|
|
15
|
+
instances =
|
|
16
|
+
if input[:all] || input[:instance] == "all"
|
|
17
|
+
app.instances
|
|
18
|
+
else
|
|
19
|
+
app.instances.select { |i| i.id == input[:instance] }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
if instances.empty?
|
|
23
|
+
if input[:all]
|
|
24
|
+
fail "No instances found."
|
|
25
|
+
else
|
|
26
|
+
fail "Instance #{app.name} \##{input[:instance]} not found."
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
spaced(instances) do |i|
|
|
31
|
+
show_instance_logs(app, i)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
desc "Print out the logs for an app's crashed instances"
|
|
36
|
+
group :apps, :info, :hidden => true
|
|
37
|
+
input :app, :desc => "Application to get the logs of", :argument => true,
|
|
38
|
+
:from_given => by_name(:app)
|
|
39
|
+
def crashlogs
|
|
40
|
+
app = input[:app]
|
|
41
|
+
|
|
42
|
+
crashes = app.crashes
|
|
43
|
+
|
|
44
|
+
fail "No crashed instances found." if crashes.empty?
|
|
45
|
+
|
|
46
|
+
most_recent = crashes.sort_by(&:since).last
|
|
47
|
+
show_instance_logs(app, most_recent)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def show_instance_logs(app, i)
|
|
51
|
+
return unless i.id
|
|
52
|
+
|
|
53
|
+
logs =
|
|
54
|
+
with_progress(
|
|
55
|
+
"Getting logs for #{c(app.name, :name)} " +
|
|
56
|
+
c("\##{i.id}", :instance)) do
|
|
57
|
+
i.files("logs")
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
line unless quiet?
|
|
61
|
+
|
|
62
|
+
spaced(logs) do |log|
|
|
63
|
+
begin
|
|
64
|
+
body =
|
|
65
|
+
with_progress("Reading " + b(log.join("/"))) do |s|
|
|
66
|
+
i.file(*log)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
lines body unless body.nil?
|
|
70
|
+
line unless body.nil?
|
|
71
|
+
rescue CFoundry::NotFound
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
require "vmc/cli/app/base"
|
|
2
|
+
require "vmc/cli/app/push/sync"
|
|
3
|
+
require "vmc/cli/app/push/create"
|
|
4
|
+
require "vmc/cli/app/push/interactions"
|
|
5
|
+
|
|
6
|
+
module VMC::App
|
|
7
|
+
class Push < Base
|
|
8
|
+
include Sync
|
|
9
|
+
include Create
|
|
10
|
+
|
|
11
|
+
desc "Push an application, syncing changes if it exists"
|
|
12
|
+
group :apps, :manage
|
|
13
|
+
input :name, :desc => "Application name", :argument => :optional
|
|
14
|
+
input :path, :desc => "Path containing the bits", :default => "."
|
|
15
|
+
input :host, :desc => "Subdomain for the app's URL"
|
|
16
|
+
input :domain, :desc => "Domain for the app",
|
|
17
|
+
:from_given => proc { |given, app|
|
|
18
|
+
if !v2? || given == "none"
|
|
19
|
+
given
|
|
20
|
+
else
|
|
21
|
+
app.space.domain_by_name(given) ||
|
|
22
|
+
fail_unknown("domain", given)
|
|
23
|
+
end
|
|
24
|
+
}
|
|
25
|
+
input :infra, :desc => "Infrastructure to use", :from_given => by_name(:infra)
|
|
26
|
+
input :url, :desc => "URL to bind to app"
|
|
27
|
+
input :memory, :desc => "Memory limit"
|
|
28
|
+
input :instances, :desc => "Number of instances to run", :type => :integer
|
|
29
|
+
input :framework, :desc => "Framework to use", :from_given => by_name(:framework)
|
|
30
|
+
input :runtime, :desc => "Runtime to use", :from_given => by_name(:runtime)
|
|
31
|
+
input :command, :desc => "Startup command"
|
|
32
|
+
input :plan, :desc => "Application plan", :default => "D100"
|
|
33
|
+
input :start, :desc => "Start app after pushing?", :default => true
|
|
34
|
+
input :restart, :desc => "Restart app after updating?", :default => true
|
|
35
|
+
input :buildpack, :desc => "Custom buildpack URL", :default => nil
|
|
36
|
+
input :create_services, :desc => "Interactively create services?",
|
|
37
|
+
:type => :boolean, :default => proc { force? ? false : interact }
|
|
38
|
+
input :bind_services, :desc => "Interactively bind services?",
|
|
39
|
+
:type => :boolean, :default => proc { force? ? false : interact }
|
|
40
|
+
interactions PushInteractions
|
|
41
|
+
|
|
42
|
+
def push
|
|
43
|
+
name = input[:name]
|
|
44
|
+
path = File.expand_path(input[:path])
|
|
45
|
+
app = client.app_by_name(name)
|
|
46
|
+
|
|
47
|
+
if app
|
|
48
|
+
sync_app(app, path)
|
|
49
|
+
else
|
|
50
|
+
setup_new_app(path)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def sync_app(app, path)
|
|
55
|
+
upload_app(app, path)
|
|
56
|
+
apply_changes(app)
|
|
57
|
+
display_changes(app)
|
|
58
|
+
commit_changes(app)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def setup_new_app(path)
|
|
62
|
+
self.path = path
|
|
63
|
+
app = create_app(get_inputs)
|
|
64
|
+
# map_route(app)
|
|
65
|
+
create_services(app)
|
|
66
|
+
bind_services(app)
|
|
67
|
+
upload_app(app, path)
|
|
68
|
+
start_app(app)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
def url_choices(name, infra)
|
|
74
|
+
if v2?
|
|
75
|
+
client.current_space.domains.sort_by(&:name).collect do |d|
|
|
76
|
+
# TODO: check availability
|
|
77
|
+
"#{name}.#{d.name}"
|
|
78
|
+
end
|
|
79
|
+
else
|
|
80
|
+
%W(#{name}.#{infra.base})
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def upload_app(app, path)
|
|
85
|
+
app = filter(:push_app, app)
|
|
86
|
+
|
|
87
|
+
with_progress("Uploading #{c(app.name, :name)}") do
|
|
88
|
+
app.upload(path)
|
|
89
|
+
end
|
|
90
|
+
rescue
|
|
91
|
+
err "Upload failed. Try again with 'af push'."
|
|
92
|
+
raise
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def wrap_message_format_errors
|
|
96
|
+
yield
|
|
97
|
+
rescue CFoundry::MessageParseError => e
|
|
98
|
+
md = e.description.match /Field: ([^,]+)/
|
|
99
|
+
field = md[1]
|
|
100
|
+
|
|
101
|
+
case field
|
|
102
|
+
when "buildpack"
|
|
103
|
+
fail "Buildpack must be a public git repository URI."
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
require "vmc/detect"
|
|
2
|
+
|
|
3
|
+
module VMC::App
|
|
4
|
+
module Create
|
|
5
|
+
attr_accessor :input
|
|
6
|
+
attr_writer :path
|
|
7
|
+
|
|
8
|
+
def get_inputs
|
|
9
|
+
inputs = {}
|
|
10
|
+
inputs[:name] = name = input[:name]
|
|
11
|
+
inputs[:infra] = infra = determine_infra
|
|
12
|
+
inputs[:url] = input[:url, name, infra]
|
|
13
|
+
inputs[:uris] = [inputs[:url]]
|
|
14
|
+
inputs[:total_instances] = input[:instances]
|
|
15
|
+
inputs[:space] = client.current_space if client.current_space
|
|
16
|
+
inputs[:production] = !!(input[:plan] =~ /^p/i) if v2?
|
|
17
|
+
inputs[:framework] = framework = determine_framework
|
|
18
|
+
inputs[:command] = input[:command] if can_have_custom_start_command?(framework)
|
|
19
|
+
inputs[:runtime] = determine_runtime(framework)
|
|
20
|
+
inputs[:buildpack] = input[:buildpack] if v2?
|
|
21
|
+
|
|
22
|
+
human_mb = human_mb(detector.suggested_memory(framework) || 64)
|
|
23
|
+
inputs[:memory] = megabytes(input[:memory, human_mb])
|
|
24
|
+
|
|
25
|
+
inputs
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def determine_infra
|
|
29
|
+
return input[:infra] if input.has?(:infra)
|
|
30
|
+
|
|
31
|
+
input[:infra, detector.all_infras, nil, nil]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def determine_framework
|
|
35
|
+
return input[:framework] if input.has?(:framework)
|
|
36
|
+
|
|
37
|
+
if (detected_framework = detector.detect_framework)
|
|
38
|
+
input[:framework, [detected_framework], detected_framework, :other]
|
|
39
|
+
else
|
|
40
|
+
input[:framework, detector.all_frameworks, nil, nil]
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def determine_runtime(framework)
|
|
45
|
+
return input[:runtime] if input.has?(:runtime)
|
|
46
|
+
|
|
47
|
+
detected_runtimes =
|
|
48
|
+
if framework.name == "standalone"
|
|
49
|
+
detector.detect_runtimes
|
|
50
|
+
else
|
|
51
|
+
detector.runtimes(framework)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
default_runtime = detected_runtimes.size == 1 ? detected_runtimes.first : nil
|
|
55
|
+
|
|
56
|
+
if detected_runtimes.empty?
|
|
57
|
+
input[:runtime, detector.all_runtimes, nil, nil]
|
|
58
|
+
else
|
|
59
|
+
input[:runtime, detected_runtimes, default_runtime, :other]
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def create_app(inputs)
|
|
64
|
+
app = client.app
|
|
65
|
+
|
|
66
|
+
inputs.each { |key, value| app.send(:"#{key}=", value) }
|
|
67
|
+
|
|
68
|
+
app = filter(:create_app, app)
|
|
69
|
+
|
|
70
|
+
with_progress("Creating #{c(app.name, :name)}") do
|
|
71
|
+
wrap_message_format_errors do
|
|
72
|
+
app.create!
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
app
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def map_route(app)
|
|
80
|
+
line unless quiet?
|
|
81
|
+
|
|
82
|
+
host = input[:host, app.name] if v2?
|
|
83
|
+
domain = input[:domain, app]
|
|
84
|
+
|
|
85
|
+
mapped_url = false
|
|
86
|
+
until domain == "none" || !domain || mapped_url
|
|
87
|
+
begin
|
|
88
|
+
host = "" if host == "none"
|
|
89
|
+
invoke :map, :app => app, :host => host, :domain => domain
|
|
90
|
+
mapped_url = true
|
|
91
|
+
rescue CFoundry::RouteHostTaken, CFoundry::UriAlreadyTaken => e
|
|
92
|
+
raise if force?
|
|
93
|
+
|
|
94
|
+
line c(e.description, :bad)
|
|
95
|
+
line
|
|
96
|
+
|
|
97
|
+
input.forget(:host) if v2?
|
|
98
|
+
input.forget(:domain)
|
|
99
|
+
|
|
100
|
+
host = input[:host, app.name] if v2?
|
|
101
|
+
domain = input[:domain, app]
|
|
102
|
+
|
|
103
|
+
# version bumps on v1 even though mapping fails
|
|
104
|
+
app.invalidate! unless v2?
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def create_services(app)
|
|
110
|
+
return unless input[:create_services]
|
|
111
|
+
|
|
112
|
+
while true
|
|
113
|
+
invoke :create_service, { :app => app }, :plan => :interact
|
|
114
|
+
break unless ask("Create another service?", :default => false)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def bind_services(app)
|
|
119
|
+
return unless input[:bind_services]
|
|
120
|
+
|
|
121
|
+
while true
|
|
122
|
+
invoke :bind_service, :app => app
|
|
123
|
+
break if (all_instances - app.services).empty?
|
|
124
|
+
break unless ask("Bind another service?", :default => false)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def start_app(app)
|
|
129
|
+
invoke :start, :app => app if input[:start]
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
private
|
|
133
|
+
|
|
134
|
+
def can_have_custom_start_command?(framework)
|
|
135
|
+
%w(standalone buildpack).include?(framework.name)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def all_instances
|
|
139
|
+
@all_instances ||= client.service_instances
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def detector
|
|
143
|
+
@detector ||= VMC::Detector.new(client, @path)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def target_base
|
|
147
|
+
client.target.sub(/^https?:\/\/([^\.]+\.)?(.+)\/?/, '\2')
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|