vmc 0.4.0.beta.93 → 0.4.0.beta.94
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/vmc-ng/Rakefile +21 -30
- data/vmc-ng/lib/vmc.rb +4 -3
- data/vmc-ng/lib/vmc/cli.rb +10 -9
- data/vmc-ng/lib/vmc/cli/app/app.rb +45 -0
- data/vmc-ng/lib/vmc/cli/app/apps.rb +97 -0
- data/vmc-ng/lib/vmc/cli/app/base.rb +82 -0
- data/vmc-ng/lib/vmc/cli/app/crashes.rb +41 -0
- data/vmc-ng/lib/vmc/cli/app/delete.rb +90 -0
- data/vmc-ng/lib/vmc/cli/app/deprecated.rb +11 -0
- data/vmc-ng/lib/vmc/cli/app/env.rb +86 -0
- data/vmc-ng/lib/vmc/cli/app/files.rb +85 -0
- data/vmc-ng/lib/vmc/cli/app/health.rb +27 -0
- data/vmc-ng/lib/vmc/cli/app/instances.rb +49 -0
- data/vmc-ng/lib/vmc/cli/app/logs.rb +80 -0
- data/vmc-ng/lib/vmc/cli/app/push.rb +336 -0
- data/vmc-ng/lib/vmc/cli/app/rename.rb +31 -0
- data/vmc-ng/lib/vmc/cli/app/restart.rb +23 -0
- data/vmc-ng/lib/vmc/cli/app/routes.rb +97 -0
- data/vmc-ng/lib/vmc/cli/app/scale.rb +67 -0
- data/vmc-ng/lib/vmc/cli/app/start.rb +96 -0
- data/vmc-ng/lib/vmc/cli/app/stats.rb +68 -0
- data/vmc-ng/lib/vmc/cli/app/stop.rb +29 -0
- data/vmc-ng/lib/vmc/cli/domain/add_domain.rb +27 -0
- data/vmc-ng/lib/vmc/cli/domain/base.rb +12 -0
- data/vmc-ng/lib/vmc/cli/domain/create_domain.rb +31 -0
- data/vmc-ng/lib/vmc/cli/domain/delete_domain.rb +51 -0
- data/vmc-ng/lib/vmc/cli/domain/domains.rb +43 -0
- data/vmc-ng/lib/vmc/cli/domain/remove_domain.rb +26 -0
- data/vmc-ng/lib/vmc/cli/help.rb +0 -1
- data/vmc-ng/lib/vmc/cli/interactive.rb +4 -0
- data/vmc-ng/lib/vmc/cli/route/base.rb +12 -0
- data/vmc-ng/lib/vmc/cli/route/create_route.rb +42 -0
- data/vmc-ng/lib/vmc/cli/route/delete_route.rb +42 -0
- data/vmc-ng/lib/vmc/cli/route/routes.rb +26 -0
- data/vmc-ng/lib/vmc/detect.rb +2 -2
- data/vmc-ng/lib/vmc/spec_helper.rb +1 -0
- data/vmc-ng/lib/vmc/version.rb +1 -1
- data/vmc-ng/spec/cli/app/push_spec.rb +34 -0
- data/vmc-ng/spec/cli/app/rename_spec.rb +108 -0
- data/vmc-ng/spec/cli/route/delete_route_spec.rb +160 -0
- data/vmc-ng/spec/detect_spec.rb +54 -0
- data/vmc-ng/spec/factories/app_factory.rb +9 -0
- data/vmc-ng/spec/factories/client_factory.rb +16 -0
- data/vmc-ng/spec/factories/domain_factory.rb +9 -0
- data/vmc-ng/spec/factories/factory.rb +3 -0
- data/vmc-ng/spec/factories/framework_factory.rb +9 -0
- data/vmc-ng/spec/factories/route_factory.rb +10 -0
- data/vmc-ng/spec/spec_helper.rb +17 -0
- data/vmc-ng/spec/support/interact_helpers.rb +23 -0
- metadata +135 -62
- data/vmc-ng/lib/vmc/cli/app.rb +0 -1333
- data/vmc-ng/lib/vmc/cli/domain.rb +0 -164
- data/vmc-ng/lib/vmc/cli/route.rb +0 -106
- data/vmc-ng/lib/vmc/spec_helpers.rb +0 -431
- data/vmc-ng/lib/vmc/spec_helpers/eventlog.rb +0 -277
- data/vmc-ng/lib/vmc/spec_helpers/patches.rb +0 -94
- data/vmc-ng/spec/Rakefile +0 -13
- data/vmc-ng/spec/app/app_spec.rb +0 -19
- data/vmc-ng/spec/app/apps_spec.rb +0 -79
- data/vmc-ng/spec/app/push_spec.rb +0 -74
- data/vmc-ng/spec/assets/hello-sinatra/Gemfile +0 -2
- data/vmc-ng/spec/assets/hello-sinatra/main.rb +0 -5
- data/vmc-ng/spec/assets/hello-sinatra/manifest.yml +0 -9
- data/vmc-ng/spec/helpers.rb +0 -7
- data/vmc-ng/spec/start/target_spec.rb +0 -60
@@ -0,0 +1,86 @@
|
|
1
|
+
require "vmc/cli/app/base"
|
2
|
+
|
3
|
+
module VMC::App
|
4
|
+
class Env < Base
|
5
|
+
VALID_ENV_VAR = /^[a-zA-Za-z_][[:alnum:]_]*$/
|
6
|
+
|
7
|
+
desc "Show all environment variables set for an app"
|
8
|
+
group :apps, :info, :hidden => true
|
9
|
+
input :app, :argument => true,
|
10
|
+
:desc => "Application to inspect the environment of",
|
11
|
+
:from_given => by_name("app")
|
12
|
+
def env
|
13
|
+
app = input[:app]
|
14
|
+
|
15
|
+
vars =
|
16
|
+
with_progress("Getting env for #{c(app.name, :name)}") do |s|
|
17
|
+
app.env
|
18
|
+
end
|
19
|
+
|
20
|
+
line unless quiet?
|
21
|
+
|
22
|
+
vars.each do |name, val|
|
23
|
+
line "#{c(name, :name)}: #{val}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "Set an environment variable"
|
28
|
+
group :apps, :info, :hidden => true
|
29
|
+
input :app, :argument => true,
|
30
|
+
:desc => "Application to set the variable for",
|
31
|
+
:from_given => by_name("app")
|
32
|
+
input :name, :argument => true,
|
33
|
+
:desc => "Environment variable name"
|
34
|
+
input :value, :argument => :optional,
|
35
|
+
:desc => "Environment variable value"
|
36
|
+
input :restart, :type => :boolean, :default => true,
|
37
|
+
:desc => "Restart app after updating?"
|
38
|
+
def set_env
|
39
|
+
app = input[:app]
|
40
|
+
name = input[:name]
|
41
|
+
|
42
|
+
if value = input[:value]
|
43
|
+
name = input[:name]
|
44
|
+
elsif name["="]
|
45
|
+
name, value = name.split("=")
|
46
|
+
end
|
47
|
+
|
48
|
+
unless name =~ VALID_ENV_VAR
|
49
|
+
fail "Invalid variable name; must match #{VALID_ENV_VAR.inspect}"
|
50
|
+
end
|
51
|
+
|
52
|
+
with_progress("Updating #{c(app.name, :name)}") do
|
53
|
+
app.env[name] = value
|
54
|
+
app.update!
|
55
|
+
end
|
56
|
+
|
57
|
+
if app.started? && input[:restart]
|
58
|
+
invoke :restart, :app => app
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
desc "Remove an environment variable"
|
64
|
+
group :apps, :info, :hidden => true
|
65
|
+
input :app, :argument => true,
|
66
|
+
:desc => "Application to set the variable for",
|
67
|
+
:from_given => by_name("app")
|
68
|
+
input :name, :argument => true,
|
69
|
+
:desc => "Environment variable name"
|
70
|
+
input :restart, :type => :boolean, :default => true,
|
71
|
+
:desc => "Restart app after updating?"
|
72
|
+
def unset_env
|
73
|
+
app = input[:app]
|
74
|
+
name = input[:name]
|
75
|
+
|
76
|
+
with_progress("Updating #{c(app.name, :name)}") do
|
77
|
+
app.env.delete(name)
|
78
|
+
app.update!
|
79
|
+
end
|
80
|
+
|
81
|
+
if app.started? && input[:restart]
|
82
|
+
invoke :restart, :app => app
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require "vmc/cli/app/base"
|
2
|
+
|
3
|
+
module VMC::App
|
4
|
+
class Files < Base
|
5
|
+
desc "Print out an app's file contents"
|
6
|
+
group :apps, :info, :hidden => true
|
7
|
+
input :app, :argument => true,
|
8
|
+
:desc => "Application to inspect the files of",
|
9
|
+
:from_given => by_name("app")
|
10
|
+
input :path, :argument => true, :default => "/",
|
11
|
+
:desc => "Path of file to read"
|
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, :argument => true,
|
39
|
+
:desc => "Application to inspect the files of",
|
40
|
+
:from_given => by_name("app")
|
41
|
+
input :path, :argument => :optional, :default => "/",
|
42
|
+
:desc => "Path of directory to list"
|
43
|
+
def files
|
44
|
+
app = input[:app]
|
45
|
+
path = input[:path]
|
46
|
+
|
47
|
+
if quiet?
|
48
|
+
files =
|
49
|
+
with_progress("Getting file listing") do
|
50
|
+
app.files(*path.split("/"))
|
51
|
+
end
|
52
|
+
|
53
|
+
files.each do |file|
|
54
|
+
line file.join("/")
|
55
|
+
end
|
56
|
+
else
|
57
|
+
invoke :file, :app => app, :path => path
|
58
|
+
end
|
59
|
+
rescue CFoundry::NotFound
|
60
|
+
fail "Invalid path #{b(path)} for app #{b(app.name)}"
|
61
|
+
rescue CFoundry::FileError => e
|
62
|
+
fail e.description
|
63
|
+
end
|
64
|
+
|
65
|
+
desc "Stream an app's file contents"
|
66
|
+
group :apps, :info, :hidden => true
|
67
|
+
input :app, :argument => true,
|
68
|
+
:desc => "Application to inspect the file of",
|
69
|
+
:from_given => by_name("app")
|
70
|
+
input :path, :argument => true, :default => "/",
|
71
|
+
:desc => "Path of file to stream"
|
72
|
+
def tail
|
73
|
+
app = input[:app]
|
74
|
+
path = input[:path]
|
75
|
+
|
76
|
+
app.stream_file(*path.split("/")) do |contents|
|
77
|
+
print contents
|
78
|
+
end
|
79
|
+
rescue CFoundry::NotFound
|
80
|
+
fail "Invalid path #{b(path)} for app #{b(app.name)}"
|
81
|
+
rescue CFoundry::FileError => e
|
82
|
+
fail e.description
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,27 @@
|
|
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, :argument => :splat, :singular => :app,
|
8
|
+
:desc => "Applications to start",
|
9
|
+
:from_given => by_name("app")
|
10
|
+
def health
|
11
|
+
apps = input[:apps]
|
12
|
+
fail "No applications given." if apps.empty?
|
13
|
+
|
14
|
+
health =
|
15
|
+
with_progress("Getting health status") do
|
16
|
+
apps.collect { |a| [a, app_status(a)] }
|
17
|
+
end
|
18
|
+
|
19
|
+
line unless quiet?
|
20
|
+
|
21
|
+
spaced(health) do |app, status|
|
22
|
+
start_line "#{c(app.name, :name)}: " unless quiet?
|
23
|
+
puts status
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,49 @@
|
|
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, :argument => :splat, :singular => :app,
|
8
|
+
:desc => "Applications whose instances to list",
|
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
|
+
spaced(instances) do |i|
|
21
|
+
if quiet?
|
22
|
+
line i.id
|
23
|
+
else
|
24
|
+
display_instance(i)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def display_instance(i)
|
31
|
+
start_line "instance #{c("\##{i.id}", :instance)}: "
|
32
|
+
puts "#{b(c(i.state.downcase, state_color(i.state)))} "
|
33
|
+
|
34
|
+
indented do
|
35
|
+
if s = i.since
|
36
|
+
line "started: #{c(s.strftime("%F %r"), :neutral)}"
|
37
|
+
end
|
38
|
+
|
39
|
+
if d = i.debugger
|
40
|
+
line "debugger: port #{b(d[:port])} at #{b(d[:ip])}"
|
41
|
+
end
|
42
|
+
|
43
|
+
if c = i.console
|
44
|
+
line "console: port #{b(c[:port])} at #{b(c[:ip])}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,80 @@
|
|
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, :argument => true,
|
8
|
+
:desc => "Application to get the logs of",
|
9
|
+
:from_given => by_name("app")
|
10
|
+
input :instance, :default => "0",
|
11
|
+
:desc => "Instance of application to get the logs of"
|
12
|
+
input :all, :type => :boolean, :default => false,
|
13
|
+
:desc => "Get logs for every instance"
|
14
|
+
def logs
|
15
|
+
app = input[:app]
|
16
|
+
|
17
|
+
instances =
|
18
|
+
if input[:all] || input[:instance] == "all"
|
19
|
+
app.instances
|
20
|
+
else
|
21
|
+
app.instances.select { |i| i.id == input[:instance] }
|
22
|
+
end
|
23
|
+
|
24
|
+
if instances.empty?
|
25
|
+
if input[:all]
|
26
|
+
fail "No instances found."
|
27
|
+
else
|
28
|
+
fail "Instance #{app.name} \##{input[:instance]} not found."
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
spaced(instances) do |i|
|
33
|
+
show_instance_logs(app, i)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "Print out the logs for an app's crashed instances"
|
38
|
+
group :apps, :info, :hidden => true
|
39
|
+
input :app, :argument => true,
|
40
|
+
:desc => "Application to get the logs of",
|
41
|
+
:from_given => by_name("app")
|
42
|
+
def crashlogs
|
43
|
+
app = input[:app]
|
44
|
+
|
45
|
+
crashes = app.crashes
|
46
|
+
|
47
|
+
fail "No crashed instances found." if crashes.empty?
|
48
|
+
|
49
|
+
spaced(crashes) do |i|
|
50
|
+
show_instance_logs(app, i)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def show_instance_logs(app, i)
|
55
|
+
return unless i.id
|
56
|
+
|
57
|
+
logs =
|
58
|
+
with_progress(
|
59
|
+
"Getting logs for #{c(app.name, :name)} " +
|
60
|
+
c("\##{i.id}", :instance)) do
|
61
|
+
i.files("logs")
|
62
|
+
end
|
63
|
+
|
64
|
+
line unless quiet?
|
65
|
+
|
66
|
+
spaced(logs) do |log|
|
67
|
+
begin
|
68
|
+
body =
|
69
|
+
with_progress("Reading " + b(log.join("/"))) do |s|
|
70
|
+
i.file(*log)
|
71
|
+
end
|
72
|
+
|
73
|
+
lines body
|
74
|
+
line unless body.empty?
|
75
|
+
rescue CFoundry::NotFound
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,336 @@
|
|
1
|
+
require "vmc/detect"
|
2
|
+
|
3
|
+
require "vmc/cli/app/base"
|
4
|
+
|
5
|
+
module VMC::App
|
6
|
+
class Push < Base
|
7
|
+
desc "Push an application, syncing changes if it exists"
|
8
|
+
group :apps, :manage
|
9
|
+
input(:name, :argument => true, :desc => "Application name") {
|
10
|
+
ask("Name")
|
11
|
+
}
|
12
|
+
input :path, :default => ".",
|
13
|
+
:desc => "Path containing the application"
|
14
|
+
input(:url, :desc => "URL bound to app") { |name|
|
15
|
+
choices = url_choices(name)
|
16
|
+
|
17
|
+
options = {
|
18
|
+
:choices => choices + ["none"],
|
19
|
+
:allow_other => true
|
20
|
+
}
|
21
|
+
|
22
|
+
options[:default] = choices.first if choices.size == 1
|
23
|
+
|
24
|
+
url = ask "URL", options
|
25
|
+
|
26
|
+
unless url == "none"
|
27
|
+
url
|
28
|
+
end
|
29
|
+
}
|
30
|
+
input(:memory, :desc => "Memory limit") { |default|
|
31
|
+
ask("Memory Limit",
|
32
|
+
:choices => memory_choices,
|
33
|
+
:allow_other => true,
|
34
|
+
:default => default || "64M")
|
35
|
+
}
|
36
|
+
input(:instances, :type => :integer,
|
37
|
+
:desc => "Number of instances to run") {
|
38
|
+
ask("Instances", :default => 1)
|
39
|
+
}
|
40
|
+
input(:framework, :from_given => find_by_name("framework"),
|
41
|
+
:desc => "Framework to use") { |all, choices, default, other|
|
42
|
+
ask_with_other("Framework", all, choices, default, other)
|
43
|
+
}
|
44
|
+
input(:runtime, :from_given => find_by_name("runtime"),
|
45
|
+
:desc => "Runtime to use") { |all, choices, default, other|
|
46
|
+
ask_with_other("Runtime", all, choices, default, other)
|
47
|
+
}
|
48
|
+
input(:command, :desc => "Startup command for standalone app") {
|
49
|
+
ask("Startup command")
|
50
|
+
}
|
51
|
+
input :plan, :default => "D100",
|
52
|
+
:desc => "Application plan (e.g. D100, P200)"
|
53
|
+
input :start, :type => :boolean, :default => true,
|
54
|
+
:desc => "Start app after pushing?"
|
55
|
+
input :restart, :type => :boolean, :default => true,
|
56
|
+
:desc => "Restart app after updating?"
|
57
|
+
input(:create_services, :type => :boolean,
|
58
|
+
:desc => "Interactively create services?") {
|
59
|
+
line unless quiet?
|
60
|
+
ask "Create services for application?", :default => false
|
61
|
+
}
|
62
|
+
input(:bind_services, :type => :boolean,
|
63
|
+
:desc => "Interactively bind services?") {
|
64
|
+
ask "Bind other services to application?", :default => false
|
65
|
+
}
|
66
|
+
def push
|
67
|
+
name = input[:name]
|
68
|
+
path = File.expand_path(input[:path])
|
69
|
+
|
70
|
+
if app = client.app_by_name(name)
|
71
|
+
sync_app(app, path)
|
72
|
+
else
|
73
|
+
create_app(name, path)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def sync_app(app, path)
|
78
|
+
upload_app(app, path)
|
79
|
+
|
80
|
+
diff = {}
|
81
|
+
|
82
|
+
if input.given?(:memory)
|
83
|
+
mem = megabytes(input[:memory])
|
84
|
+
|
85
|
+
if mem != app.memory
|
86
|
+
diff[:memory] = [app.memory, mem]
|
87
|
+
app.memory = mem
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
if input.given?(:instances)
|
92
|
+
instances = input[:instances]
|
93
|
+
|
94
|
+
if instances != app.total_instances
|
95
|
+
diff[:instances] = [app.total_instances, instances]
|
96
|
+
app.total_instances = instances
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
if input.given?(:framework)
|
101
|
+
all_frameworks = client.frameworks
|
102
|
+
|
103
|
+
framework = input[:framework, all_frameworks, all_frameworks]
|
104
|
+
|
105
|
+
if framework != app.framework
|
106
|
+
diff[:framework] = [app.framework.name, framework.name]
|
107
|
+
app.framework = framework
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
if input.given?(:runtime)
|
112
|
+
all_runtimes = client.runtimes
|
113
|
+
|
114
|
+
runtime = input[:runtime, all_runtimes, all_runtimes]
|
115
|
+
|
116
|
+
if runtime != app.runtime
|
117
|
+
diff[:runtime] = [app.runtime.name, runtime.name]
|
118
|
+
app.runtime = runtime
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
if input.given?(:command) && input[:command] != app.command
|
123
|
+
command = input[:command]
|
124
|
+
|
125
|
+
if command != app.command
|
126
|
+
diff[:command] = [app.command, command]
|
127
|
+
app.command = command
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
if input.given?(:plan) && v2?
|
132
|
+
production = !!(input[:plan] =~ /^p/i)
|
133
|
+
|
134
|
+
if production != app.production
|
135
|
+
diff[:production] = [bool(app.production), bool(production)]
|
136
|
+
app.production = production
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
unless diff.empty?
|
141
|
+
line "Changes:"
|
142
|
+
|
143
|
+
indented do
|
144
|
+
diff.each do |name, change|
|
145
|
+
old, new = change
|
146
|
+
line "#{c(name, :name)}: #{old} #{c("->", :dim)} #{new}"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
with_progress("Updating #{c(app.name, :name)}") do
|
151
|
+
app.update!
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
if input[:restart] && app.started?
|
156
|
+
invoke :restart, :app => app
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def create_app(name, path)
|
161
|
+
app = client.app
|
162
|
+
app.name = name
|
163
|
+
app.space = client.current_space if client.current_space
|
164
|
+
app.total_instances = input[:instances]
|
165
|
+
app.production = !!(input[:plan] =~ /^p/i) if v2?
|
166
|
+
|
167
|
+
detector = VMC::Detector.new(client, path)
|
168
|
+
all_frameworks = detector.all_frameworks
|
169
|
+
all_runtimes = detector.all_runtimes
|
170
|
+
|
171
|
+
if detected_framework = detector.detect_framework
|
172
|
+
framework = input[
|
173
|
+
:framework,
|
174
|
+
all_frameworks,
|
175
|
+
[detected_framework],
|
176
|
+
detected_framework,
|
177
|
+
:other
|
178
|
+
]
|
179
|
+
else
|
180
|
+
framework = input[:framework, all_frameworks, all_frameworks]
|
181
|
+
end
|
182
|
+
|
183
|
+
|
184
|
+
if framework.name == "standalone"
|
185
|
+
detected_runtimes = detector.detect_runtimes
|
186
|
+
else
|
187
|
+
detected_runtimes = detector.runtimes(framework)
|
188
|
+
end
|
189
|
+
|
190
|
+
if detected_runtimes.size == 1
|
191
|
+
default_runtime = detected_runtimes.first
|
192
|
+
end
|
193
|
+
|
194
|
+
if detected_runtimes.empty?
|
195
|
+
runtime = input[:runtime, all_runtimes, all_runtimes]
|
196
|
+
else
|
197
|
+
runtime = input[
|
198
|
+
:runtime,
|
199
|
+
all_runtimes,
|
200
|
+
detected_runtimes,
|
201
|
+
default_runtime,
|
202
|
+
:other
|
203
|
+
]
|
204
|
+
end
|
205
|
+
|
206
|
+
|
207
|
+
fail "Invalid framework '#{input[:framework]}'" unless framework
|
208
|
+
fail "Invalid runtime '#{input[:runtime]}'" unless runtime
|
209
|
+
|
210
|
+
app.framework = framework
|
211
|
+
app.runtime = runtime
|
212
|
+
|
213
|
+
app.command = input[:command] if framework.name == "standalone"
|
214
|
+
|
215
|
+
default_memory = detector.suggested_memory(framework) || 64
|
216
|
+
app.memory = megabytes(input[:memory, human_mb(default_memory)])
|
217
|
+
|
218
|
+
app = filter(:create_app, app)
|
219
|
+
|
220
|
+
with_progress("Creating #{c(app.name, :name)}") do
|
221
|
+
app.create!
|
222
|
+
end
|
223
|
+
|
224
|
+
line unless quiet?
|
225
|
+
|
226
|
+
url = input[:url, name]
|
227
|
+
|
228
|
+
mapped_url = false
|
229
|
+
until !url || mapped_url
|
230
|
+
begin
|
231
|
+
invoke :map, :app => app, :url => url
|
232
|
+
mapped_url = true
|
233
|
+
rescue CFoundry::RouteHostTaken, CFoundry::UriAlreadyTaken => e
|
234
|
+
line c(e.description, :bad)
|
235
|
+
line
|
236
|
+
|
237
|
+
input.forget(:url)
|
238
|
+
url = input[:url, name]
|
239
|
+
|
240
|
+
# version bumps on v1 even though mapping fails
|
241
|
+
app.invalidate! unless v2?
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
bindings = []
|
246
|
+
|
247
|
+
if input[:create_services] && !force?
|
248
|
+
while true
|
249
|
+
invoke :create_service, { :app => app }, :plan => :interact
|
250
|
+
break unless ask "Create another service?", :default => false
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
if input[:bind_services] && !force?
|
255
|
+
instances = client.service_instances
|
256
|
+
|
257
|
+
while true
|
258
|
+
invoke :bind_service, :app => app
|
259
|
+
|
260
|
+
break if (instances - app.services).empty?
|
261
|
+
|
262
|
+
break unless ask("Bind another service?", :default => false)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
app = filter(:push_app, app)
|
267
|
+
|
268
|
+
begin
|
269
|
+
upload_app(app, path)
|
270
|
+
rescue
|
271
|
+
err "Upload failed. Try again with 'vmc push'."
|
272
|
+
raise
|
273
|
+
end
|
274
|
+
|
275
|
+
invoke :start, :app => app if input[:start]
|
276
|
+
end
|
277
|
+
|
278
|
+
private
|
279
|
+
|
280
|
+
def upload_app(app, path)
|
281
|
+
with_progress("Uploading #{c(app.name, :name)}") do
|
282
|
+
app.upload(path)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
def bool(b)
|
287
|
+
if b
|
288
|
+
c("true", :yes)
|
289
|
+
else
|
290
|
+
c("false", :no)
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
def url_choices(name)
|
295
|
+
if v2?
|
296
|
+
client.current_space.domains.sort_by(&:name).collect do |d|
|
297
|
+
# TODO: check availability
|
298
|
+
"#{name}.#{d.name}"
|
299
|
+
end
|
300
|
+
else
|
301
|
+
["#{name}.#{target_base}"]
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
def target_base
|
306
|
+
client.target.sub(/^https?:\/\/([^\.]+\.)?(.+)\/?/, '\2')
|
307
|
+
end
|
308
|
+
|
309
|
+
def ask_with_other(message, all, choices, default, other)
|
310
|
+
choices = choices.sort_by(&:name)
|
311
|
+
choices << other if other
|
312
|
+
|
313
|
+
opts = {
|
314
|
+
:choices => choices,
|
315
|
+
:display => proc { |x|
|
316
|
+
if other && x == other
|
317
|
+
"other"
|
318
|
+
else
|
319
|
+
x.name
|
320
|
+
end
|
321
|
+
}
|
322
|
+
}
|
323
|
+
|
324
|
+
opts[:default] = default if default
|
325
|
+
|
326
|
+
res = ask(message, opts)
|
327
|
+
|
328
|
+
if other && res == other
|
329
|
+
opts[:choices] = all
|
330
|
+
res = ask(message, opts)
|
331
|
+
end
|
332
|
+
|
333
|
+
res
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|