jdc 0.1.2 → 0.2.0
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 -24
- data/Rakefile +13 -0
- data/bin/jdc +12 -2
- data/lib/admin/README.md +15 -0
- data/lib/admin/curl.rb +60 -0
- data/lib/admin/guid.rb +89 -0
- data/lib/admin/plugin.rb +6 -0
- data/lib/admin/service_auth_token.rb +94 -0
- data/lib/admin/service_broker/add.rb +47 -0
- data/lib/admin/service_broker/service_brokers.rb +24 -0
- data/lib/admin/set_quota.rb +44 -0
- data/lib/console/README.md +8 -0
- data/lib/console/console.rb +187 -0
- data/lib/console/plugin.rb +33 -0
- data/lib/jdc/cli/app/app.rb +43 -0
- data/lib/jdc/cli/app/apps.rb +87 -0
- data/lib/jdc/cli/app/base.rb +72 -0
- data/lib/jdc/cli/app/delete.rb +95 -0
- data/lib/jdc/cli/app/deprecated.rb +11 -0
- data/lib/jdc/cli/app/env.rb +78 -0
- data/lib/jdc/cli/app/events.rb +45 -0
- data/lib/jdc/cli/app/files.rb +137 -0
- data/lib/jdc/cli/app/health.rb +26 -0
- data/lib/jdc/cli/app/instances.rb +53 -0
- data/lib/jdc/cli/app/logs.rb +76 -0
- data/lib/jdc/cli/app/push/create.rb +108 -0
- data/lib/jdc/cli/app/push/interactions.rb +86 -0
- data/lib/jdc/cli/app/push/sync.rb +57 -0
- data/lib/jdc/cli/app/push.rb +103 -0
- data/lib/jdc/cli/app/rename.rb +35 -0
- data/lib/jdc/cli/app/restart.rb +31 -0
- data/lib/jdc/cli/app/scale.rb +63 -0
- data/lib/jdc/cli/app/start.rb +161 -0
- data/lib/jdc/cli/app/stats.rb +67 -0
- data/lib/jdc/cli/app/stop.rb +27 -0
- data/lib/jdc/cli/domain/base.rb +9 -0
- data/lib/jdc/cli/domain/domains.rb +40 -0
- data/lib/jdc/cli/domain/map.rb +55 -0
- data/lib/jdc/cli/domain/unmap.rb +56 -0
- data/lib/jdc/cli/help.rb +15 -0
- data/lib/jdc/cli/interactive.rb +105 -0
- data/lib/jdc/cli/login_requirements.rb +15 -0
- data/lib/jdc/cli/organization/base.rb +14 -0
- data/lib/jdc/cli/organization/create.rb +37 -0
- data/lib/jdc/cli/organization/delete.rb +63 -0
- data/lib/jdc/cli/organization/org.rb +45 -0
- data/lib/jdc/cli/organization/orgs.rb +30 -0
- data/lib/jdc/cli/organization/rename.rb +37 -0
- data/lib/jdc/cli/populators/base.rb +16 -0
- data/lib/jdc/cli/populators/organization.rb +32 -0
- data/lib/jdc/cli/populators/populator_methods.rb +64 -0
- data/lib/jdc/cli/populators/space.rb +33 -0
- data/lib/jdc/cli/populators/target.rb +13 -0
- data/lib/jdc/cli/route/base.rb +9 -0
- data/lib/jdc/cli/route/delete.rb +28 -0
- data/lib/jdc/cli/route/map.rb +68 -0
- data/lib/jdc/cli/route/routes.rb +26 -0
- data/lib/jdc/cli/route/unmap.rb +56 -0
- data/lib/jdc/cli/service/base.rb +9 -0
- data/lib/jdc/cli/service/bind.rb +44 -0
- data/lib/jdc/cli/service/create.rb +159 -0
- data/lib/jdc/cli/service/delete.rb +83 -0
- data/lib/jdc/cli/service/rename.rb +36 -0
- data/lib/jdc/cli/service/service.rb +42 -0
- data/lib/jdc/cli/service/service_instance_helper.rb +99 -0
- data/lib/jdc/cli/service/services.rb +111 -0
- data/lib/jdc/cli/service/unbind.rb +37 -0
- data/lib/jdc/cli/space/base.rb +29 -0
- data/lib/jdc/cli/space/create.rb +67 -0
- data/lib/jdc/cli/space/delete.rb +56 -0
- data/lib/jdc/cli/space/rename.rb +38 -0
- data/lib/jdc/cli/space/space.rb +66 -0
- data/lib/jdc/cli/space/spaces.rb +57 -0
- data/lib/jdc/cli/space/switch.rb +19 -0
- data/lib/jdc/cli/start/base.rb +41 -0
- data/lib/jdc/cli/start/colors.rb +13 -0
- data/lib/jdc/cli/start/target.rb +50 -0
- data/lib/jdc/cli/start/target_prettifier.rb +17 -0
- data/lib/jdc/cli/start/targets.rb +16 -0
- data/lib/jdc/cli/user/base.rb +30 -0
- data/lib/jdc/cli/user/create.rb +52 -0
- data/lib/jdc/cli/user/passwd.rb +37 -0
- data/lib/jdc/cli/user/register.rb +43 -0
- data/lib/jdc/cli/user/users.rb +32 -0
- data/lib/jdc/cli.rb +544 -0
- data/lib/jdc/constants.rb +11 -0
- data/lib/jdc/errors.rb +19 -0
- data/lib/jdc/object_extensions.rb +15 -0
- data/lib/jdc/plugin.rb +56 -0
- data/lib/jdc/spacing.rb +89 -0
- data/lib/jdc/spec_helper.rb +1 -0
- data/lib/jdc/test_support.rb +6 -0
- data/lib/jdc/version.rb +3 -0
- data/lib/jdc.rb +15 -2
- data/lib/manifests/errors.rb +35 -0
- data/lib/manifests/loader/builder.rb +39 -0
- data/lib/manifests/loader/normalizer.rb +145 -0
- data/lib/manifests/loader/resolver.rb +79 -0
- data/lib/manifests/loader.rb +31 -0
- data/lib/manifests/manifests.rb +344 -0
- data/lib/manifests/plugin.rb +140 -0
- data/lib/micro/README.md +9 -0
- data/lib/micro/errors.rb +4 -0
- data/lib/{jdc → micro}/micro.rb +15 -15
- data/lib/micro/plugin.rb +197 -0
- data/lib/micro/switcher/base.rb +79 -0
- data/lib/{jdc/micro → micro}/switcher/darwin.rb +5 -3
- data/lib/{jdc/micro → micro}/switcher/dummy.rb +1 -1
- data/lib/micro/switcher/linux.rb +16 -0
- data/lib/{jdc/micro → micro}/switcher/windows.rb +5 -5
- data/lib/{jdc/micro → micro}/vmrun.rb +26 -19
- data/lib/tasks/gem_release.rake +42 -0
- data/lib/tunnel/README.md +29 -0
- data/{config → lib/tunnel/config}/clients.yml +2 -2
- data/lib/tunnel/helper-app/Gemfile +10 -0
- data/lib/tunnel/helper-app/Gemfile.lock +48 -0
- data/{caldecott_helper → lib/tunnel/helper-app}/server.rb +5 -5
- data/lib/tunnel/plugin.rb +183 -0
- data/lib/tunnel/tunnel.rb +295 -0
- metadata +319 -89
- data/README.md +0 -102
- data/config/micro/paths.yml +0 -22
- data/config/micro/refresh_ip.rb +0 -20
- data/lib/cli/commands/admin.rb +0 -58
- data/lib/cli/commands/apps.rb +0 -1129
- data/lib/cli/commands/base.rb +0 -228
- data/lib/cli/commands/manifest.rb +0 -56
- data/lib/cli/commands/micro.rb +0 -115
- data/lib/cli/commands/misc.rb +0 -126
- data/lib/cli/commands/services.rb +0 -178
- data/lib/cli/commands/user.rb +0 -14
- data/lib/cli/config.rb +0 -173
- data/lib/cli/console_helper.rb +0 -170
- data/lib/cli/core_ext.rb +0 -122
- data/lib/cli/errors.rb +0 -19
- data/lib/cli/frameworks.rb +0 -265
- data/lib/cli/manifest_helper.rb +0 -302
- data/lib/cli/runner.rb +0 -505
- data/lib/cli/services_helper.rb +0 -84
- data/lib/cli/tunnel_helper.rb +0 -332
- data/lib/cli/usage.rb +0 -86
- data/lib/cli/version.rb +0 -7
- data/lib/cli/zip_util.rb +0 -77
- data/lib/cli.rb +0 -53
- data/lib/jdc/client.rb +0 -457
- data/lib/jdc/const.rb +0 -25
- data/lib/jdc/micro/switcher/base.rb +0 -97
- data/lib/jdc/micro/switcher/linux.rb +0 -16
- data/lib/jdc/signature/version.rb +0 -27
- data/lib/jdc/signer.rb +0 -13
- data/lib/jdc/timer.rb +0 -12
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
module JDC::App
|
|
2
|
+
module Create
|
|
3
|
+
attr_accessor :input
|
|
4
|
+
attr_writer :path
|
|
5
|
+
|
|
6
|
+
def get_inputs
|
|
7
|
+
inputs = {}
|
|
8
|
+
inputs[:name] = input[:name]
|
|
9
|
+
inputs[:total_instances] = input[:instances]
|
|
10
|
+
inputs[:space] = client.current_space if client.current_space
|
|
11
|
+
|
|
12
|
+
inputs[:buildpack] = input[:buildpack]
|
|
13
|
+
inputs[:command] = input[:command] if input.has?(:command) || !has_procfile?
|
|
14
|
+
|
|
15
|
+
inputs[:memory] = megabytes(input[:memory, human_mb(256)])
|
|
16
|
+
inputs[:stack] = input[:stack]
|
|
17
|
+
|
|
18
|
+
inputs
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def create_app(inputs)
|
|
22
|
+
app = client.app
|
|
23
|
+
|
|
24
|
+
inputs.each { |key, value| app.send(:"#{key}=", value) }
|
|
25
|
+
finalize
|
|
26
|
+
|
|
27
|
+
app = filter(:create_app, app)
|
|
28
|
+
|
|
29
|
+
with_progress("Creating #{c(app.name, :name)}") do
|
|
30
|
+
wrap_message_format_errors do
|
|
31
|
+
begin
|
|
32
|
+
app.create!
|
|
33
|
+
rescue JFoundry::NotAuthorized
|
|
34
|
+
fail "You need the Project Developer role in #{b(client.current_space.name)} to push."
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
app
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def map_route(app)
|
|
43
|
+
line unless quiet?
|
|
44
|
+
|
|
45
|
+
host = input[:host, app.name]
|
|
46
|
+
finalize
|
|
47
|
+
domain = input[:domain, app]
|
|
48
|
+
finalize
|
|
49
|
+
|
|
50
|
+
mapped_url = false
|
|
51
|
+
until domain == "none" || !domain || mapped_url
|
|
52
|
+
begin
|
|
53
|
+
host = "" if host == "none"
|
|
54
|
+
invoke :map, :app => app, :host => host, :domain => domain
|
|
55
|
+
mapped_url = true
|
|
56
|
+
rescue JFoundry::RouteHostTaken, JFoundry::UriAlreadyTaken => e
|
|
57
|
+
raise if force?
|
|
58
|
+
|
|
59
|
+
line c(e.description, :bad)
|
|
60
|
+
line
|
|
61
|
+
|
|
62
|
+
input.forget(:host)
|
|
63
|
+
input.forget(:domain)
|
|
64
|
+
|
|
65
|
+
host = input[:host, app.name]
|
|
66
|
+
domain = input[:domain, app]
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def create_services(app)
|
|
72
|
+
return unless input[:create_services]
|
|
73
|
+
finalize
|
|
74
|
+
while true
|
|
75
|
+
invoke :create_service, { :app => app }, :plan => :interact
|
|
76
|
+
break unless ask("Create another service?", :default => false)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def bind_services(app)
|
|
81
|
+
return unless input[:bind_services]
|
|
82
|
+
|
|
83
|
+
while true
|
|
84
|
+
invoke :bind_service, :app => app
|
|
85
|
+
break if (all_instances - app.services).empty?
|
|
86
|
+
break unless ask("Bind another service?", :default => false)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def start_app(app)
|
|
91
|
+
invoke :start, :app => app if input[:start]
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private
|
|
95
|
+
|
|
96
|
+
def has_procfile?
|
|
97
|
+
File.exists?("#@path/Procfile")
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def all_instances
|
|
101
|
+
@all_instances ||= client.service_instances
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def target_base
|
|
105
|
+
client.target.sub(/^https?:\/\/([^\.]+\.)?(.+)\/?/, '\2')
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
module JDC::App
|
|
2
|
+
module PushInteractions
|
|
3
|
+
def ask_name
|
|
4
|
+
ask("Name")
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def ask_host(name)
|
|
8
|
+
ask "Subdomain", :choices => [name, "none"],
|
|
9
|
+
:default => name,
|
|
10
|
+
:allow_other => true
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def ask_domain(app)
|
|
14
|
+
choices = app.space.domains
|
|
15
|
+
|
|
16
|
+
options = {
|
|
17
|
+
:choices => choices + ["none"],
|
|
18
|
+
:display => proc { |choice| choice.is_a?(String) ? choice : choice.name },
|
|
19
|
+
:allow_other => true
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
options[:default] = choices.first
|
|
23
|
+
|
|
24
|
+
ask "Domain", options
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def ask_memory(default)
|
|
28
|
+
ask("Memory Limit",
|
|
29
|
+
:choices => memory_choices,
|
|
30
|
+
:allow_other => true,
|
|
31
|
+
:default => default || "128M")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def ask_instances
|
|
35
|
+
ask("Instances", :default => 1)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def ask_command
|
|
39
|
+
command = ask("Custom startup command", :default => "none")
|
|
40
|
+
|
|
41
|
+
if command != "none"
|
|
42
|
+
command
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def ask_create_services
|
|
47
|
+
line unless quiet?
|
|
48
|
+
ask "Create services for application?", :default => false
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def ask_bind_services
|
|
52
|
+
return if all_instances.empty?
|
|
53
|
+
|
|
54
|
+
ask "Bind other services to application?", :default => false
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def ask_with_other(message, all, choices, default, other)
|
|
60
|
+
choices = choices.sort_by(&:name)
|
|
61
|
+
choices << other if other
|
|
62
|
+
|
|
63
|
+
opts = {
|
|
64
|
+
:choices => choices,
|
|
65
|
+
:display => proc { |x|
|
|
66
|
+
if other && x == other
|
|
67
|
+
"other"
|
|
68
|
+
else
|
|
69
|
+
x.name
|
|
70
|
+
end
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
opts[:default] = default if default
|
|
75
|
+
|
|
76
|
+
res = ask(message, opts)
|
|
77
|
+
|
|
78
|
+
if other && res == other
|
|
79
|
+
opts[:choices] = all
|
|
80
|
+
res = ask(message, opts)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
res
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module JDC::App
|
|
2
|
+
module Sync
|
|
3
|
+
def apply_changes(app)
|
|
4
|
+
app.memory = megabytes(input[:memory]) if input.has?(:memory)
|
|
5
|
+
app.total_instances = input[:instances] if input.has?(:instances)
|
|
6
|
+
app.command = input[:command] if input.has?(:command)
|
|
7
|
+
app.buildpack = input[:buildpack] if input.has?(:buildpack)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def display_changes(app)
|
|
11
|
+
return unless app.changed?
|
|
12
|
+
|
|
13
|
+
line "Changes:"
|
|
14
|
+
|
|
15
|
+
indented do
|
|
16
|
+
app.changes.each do |attr, (old, new)|
|
|
17
|
+
line "#{c(attr, :name)}: #{diff_str(attr, old)} -> #{diff_str(attr, new)}"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def commit_changes(app)
|
|
23
|
+
if app.changed?
|
|
24
|
+
with_progress("Updating #{c(app.name, :name)}") do
|
|
25
|
+
wrap_message_format_errors do
|
|
26
|
+
app.update!
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
if input[:restart] && app.started?
|
|
32
|
+
invoke :restart, :app => app
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def diff_str(attr, val)
|
|
39
|
+
case attr
|
|
40
|
+
when :memory
|
|
41
|
+
human_mb(val)
|
|
42
|
+
when :command, :buildpack
|
|
43
|
+
"'#{val}'"
|
|
44
|
+
else
|
|
45
|
+
val
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def bool(b)
|
|
50
|
+
if b
|
|
51
|
+
c("true", :yes)
|
|
52
|
+
else
|
|
53
|
+
c("false", :no)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
require "jdc/cli/app/base"
|
|
2
|
+
require "jdc/cli/app/push/sync"
|
|
3
|
+
require "jdc/cli/app/push/create"
|
|
4
|
+
require "jdc/cli/app/push/interactions"
|
|
5
|
+
|
|
6
|
+
module JDC::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 given == "none"
|
|
19
|
+
given
|
|
20
|
+
else
|
|
21
|
+
app.space.domain_by_name(given) ||
|
|
22
|
+
fail_unknown("domain", given)
|
|
23
|
+
end
|
|
24
|
+
}
|
|
25
|
+
input :memory, :desc => "Memory limit"
|
|
26
|
+
input :instances, :desc => "Number of instances to run", :type => :integer
|
|
27
|
+
input :command, :desc => "Startup command", :default => nil
|
|
28
|
+
input :plan, :desc => "Application plan"
|
|
29
|
+
input :start, :desc => "Start app after pushing?", :default => true
|
|
30
|
+
input :restart, :desc => "Restart app after updating?", :default => true
|
|
31
|
+
input :buildpack, :desc => "Custom buildpack URL", :default => nil
|
|
32
|
+
input :stack, :desc => "Stack to use", :default => nil,
|
|
33
|
+
:from_given => by_name(:stack)
|
|
34
|
+
input :create_services, :desc => "Interactively create services?",
|
|
35
|
+
:type => :boolean, :default => proc { force? ? false : interact }
|
|
36
|
+
input :bind_services, :desc => "Interactively bind services?",
|
|
37
|
+
:type => :boolean, :default => proc { force? ? false : interact }
|
|
38
|
+
interactions PushInteractions
|
|
39
|
+
|
|
40
|
+
def push
|
|
41
|
+
name = input[:name]
|
|
42
|
+
path = File.expand_path(input[:path])
|
|
43
|
+
app = client.app_by_name(name)
|
|
44
|
+
|
|
45
|
+
if app
|
|
46
|
+
sync_app(app, path)
|
|
47
|
+
else
|
|
48
|
+
setup_new_app(path)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def sync_app(app, path)
|
|
53
|
+
upload_app(app, path)
|
|
54
|
+
apply_changes(app)
|
|
55
|
+
display_changes(app)
|
|
56
|
+
commit_changes(app)
|
|
57
|
+
|
|
58
|
+
warn "\n#{c(app.name, :name)} is currently stopped, start it with 'jdc start'" unless app.started?
|
|
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)
|
|
74
|
+
client.current_space.domains.sort_by(&:name).collect do |d|
|
|
75
|
+
# TODO: check availability
|
|
76
|
+
"#{name}.#{d.name}"
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def upload_app(app, path)
|
|
81
|
+
app = filter(:push_app, app)
|
|
82
|
+
|
|
83
|
+
with_progress("Uploading #{c(app.name, :name)}") do
|
|
84
|
+
app.upload(path)
|
|
85
|
+
end
|
|
86
|
+
rescue
|
|
87
|
+
err "Upload failed. Try again with 'jdc push'."
|
|
88
|
+
raise
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def wrap_message_format_errors
|
|
92
|
+
yield
|
|
93
|
+
rescue JFoundry::MessageParseError => e
|
|
94
|
+
md = e.description.match /Field: ([^,]+)/
|
|
95
|
+
field = md[1]
|
|
96
|
+
|
|
97
|
+
case field
|
|
98
|
+
when "buildpack"
|
|
99
|
+
fail "Buildpack must be a public git repository URI."
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require "jdc/cli/app/base"
|
|
2
|
+
|
|
3
|
+
module JDC::App
|
|
4
|
+
class Rename < Base
|
|
5
|
+
desc "Rename an application"
|
|
6
|
+
group :apps, :manage
|
|
7
|
+
input :app, :desc => "Application to rename", :argument => :optional,
|
|
8
|
+
:from_given => by_name(:app)
|
|
9
|
+
input :name, :desc => "New application name", :argument => :optional
|
|
10
|
+
def rename
|
|
11
|
+
app = input[:app]
|
|
12
|
+
name = input[:name]
|
|
13
|
+
|
|
14
|
+
app.name = name
|
|
15
|
+
|
|
16
|
+
with_progress("Renaming to #{c(name, :name)}") do
|
|
17
|
+
app.update!
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def ask_app
|
|
24
|
+
apps = client.apps
|
|
25
|
+
fail "No applications." if apps.empty?
|
|
26
|
+
|
|
27
|
+
ask("Rename which application?", :choices => apps.sort_by(&:name),
|
|
28
|
+
:display => proc(&:name))
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def ask_name
|
|
32
|
+
ask("New name")
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require "jdc/cli/app/base"
|
|
2
|
+
|
|
3
|
+
module JDC::App
|
|
4
|
+
class Restart < Base
|
|
5
|
+
desc "Stop and start an application"
|
|
6
|
+
group :apps, :manage
|
|
7
|
+
input :apps, :desc => "Applications to start", :argument => :splat,
|
|
8
|
+
:singular => :app, :from_given => by_name(:app)
|
|
9
|
+
input :debug_mode, :desc => "Debug mode to start in", :aliases => "-d"
|
|
10
|
+
input :all, :desc => "Restart all applications", :default => false
|
|
11
|
+
|
|
12
|
+
############# Uncomment to complete 50543607
|
|
13
|
+
#input :command, :desc => "Command to restart application", :default => nil
|
|
14
|
+
|
|
15
|
+
def restart
|
|
16
|
+
invoke :stop, :all => input[:all], :apps => input[:apps]
|
|
17
|
+
|
|
18
|
+
line unless quiet?
|
|
19
|
+
|
|
20
|
+
input[:apps].each do |app|
|
|
21
|
+
unless input[:command].nil?
|
|
22
|
+
app.command = input[:command]
|
|
23
|
+
end
|
|
24
|
+
app.update!
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
invoke :start, :all => input[:all], :apps => input[:apps],
|
|
28
|
+
:debug_mode => input[:debug_mode]
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
require "jdc/cli/app/base"
|
|
2
|
+
|
|
3
|
+
module JDC::App
|
|
4
|
+
class Scale < Base
|
|
5
|
+
desc "Update the instances/memory limit for an application"
|
|
6
|
+
group :apps, :info
|
|
7
|
+
input :app, :desc => "Application to update", :argument => true,
|
|
8
|
+
:from_given => by_name(:app)
|
|
9
|
+
input :instances, :desc => "Number of instances to run",
|
|
10
|
+
:type => :numeric
|
|
11
|
+
input :memory, :desc => "Memory limit"
|
|
12
|
+
input :disk, :desc => "Disk quota"
|
|
13
|
+
input :restart, :desc => "Restart app after updating?", :default => true
|
|
14
|
+
|
|
15
|
+
def scale
|
|
16
|
+
app = input[:app]
|
|
17
|
+
|
|
18
|
+
if input.has?(:instances)
|
|
19
|
+
instances = input[:instances, app.total_instances]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
if input.has?(:memory)
|
|
23
|
+
memory = input[:memory, app.memory]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
if input.has?(:disk)
|
|
27
|
+
disk = input[:disk, human_mb(app.disk_quota)]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
unless instances || memory || disk
|
|
31
|
+
instances = input[:instances, app.total_instances]
|
|
32
|
+
memory = input[:memory, app.memory]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
app.total_instances = instances if input.has?(:instances)
|
|
36
|
+
app.memory = megabytes(memory) if input.has?(:memory)
|
|
37
|
+
app.disk_quota = megabytes(disk) if input.has?(:disk)
|
|
38
|
+
|
|
39
|
+
fail "No changes!" unless app.changed?
|
|
40
|
+
|
|
41
|
+
with_progress("Scaling #{c(app.name, :name)}") do
|
|
42
|
+
app.update!
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
needs_restart = app.changes.key?(:memory) || app.changes.key?(:disk_quota)
|
|
46
|
+
|
|
47
|
+
if needs_restart && app.started? && input[:restart]
|
|
48
|
+
invoke :restart, :app => app
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def ask_instances(default)
|
|
55
|
+
ask("Instances", :default => default)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def ask_memory(default)
|
|
59
|
+
ask("Memory Limit", :choices => memory_choices,
|
|
60
|
+
:default => human_mb(default), :allow_other => true)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
require "jdc/cli/app/base"
|
|
2
|
+
|
|
3
|
+
module JDC::App
|
|
4
|
+
class Start < Base
|
|
5
|
+
APP_CHECK_LIMIT = 60
|
|
6
|
+
|
|
7
|
+
desc "Start an application"
|
|
8
|
+
group :apps, :manage
|
|
9
|
+
input :apps, :desc => "Applications to start", :argument => :splat,
|
|
10
|
+
:singular => :app, :from_given => by_name(:app)
|
|
11
|
+
input :debug_mode, :desc => "Debug mode to start in", :aliases => "-d"
|
|
12
|
+
input :all, :desc => "Start all applications", :default => false
|
|
13
|
+
def start
|
|
14
|
+
apps = input[:all] ? client.apps : input[:apps]
|
|
15
|
+
fail "No applications given." if apps.empty?
|
|
16
|
+
|
|
17
|
+
spaced(apps) do |app|
|
|
18
|
+
app = filter(:start_app, app)
|
|
19
|
+
|
|
20
|
+
switch_mode(app, input[:debug_mode])
|
|
21
|
+
|
|
22
|
+
if app.started?
|
|
23
|
+
err "Application #{b(app.name)} is already started."
|
|
24
|
+
next
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
log = start_app(app)
|
|
28
|
+
stream_start_log(log) if log
|
|
29
|
+
check_application(app)
|
|
30
|
+
|
|
31
|
+
if !app.debug_mode.nil? && app.debug_mode != "none" && !quiet?
|
|
32
|
+
line
|
|
33
|
+
invoke :instances, :app => app
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def start_app(app)
|
|
41
|
+
log = nil
|
|
42
|
+
with_progress("Preparing to start #{c(app.name, :name)}") do
|
|
43
|
+
app.start! do |url|
|
|
44
|
+
log = url
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
log
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def stream_start_log(log)
|
|
51
|
+
offset = 0
|
|
52
|
+
|
|
53
|
+
while true
|
|
54
|
+
begin
|
|
55
|
+
client.stream_url(log + "&tail&tail_offset=#{offset}") do |out|
|
|
56
|
+
offset += out.size
|
|
57
|
+
print out
|
|
58
|
+
end
|
|
59
|
+
rescue Timeout::Error
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
rescue JFoundry::APIError
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# set app debug mode, ensuring it's valid, and shutting it down
|
|
66
|
+
def switch_mode(app, mode)
|
|
67
|
+
mode = "run" if mode == "" # no value given
|
|
68
|
+
|
|
69
|
+
return false if app.debug == mode
|
|
70
|
+
|
|
71
|
+
if mode == "none"
|
|
72
|
+
with_progress("Removing debug mode") do
|
|
73
|
+
app.debug = mode
|
|
74
|
+
app.stop! if app.started?
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
return true
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
with_progress("Switching mode to #{c(mode, :name)}") do |s|
|
|
81
|
+
app.debug = mode
|
|
82
|
+
app.stop! if app.started?
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def check_application(app)
|
|
87
|
+
if app.debug == "suspend"
|
|
88
|
+
line "Application is in suspended debugging mode."
|
|
89
|
+
line "It will wait for you to attach to it before starting."
|
|
90
|
+
return
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
print("Checking status of app '#{c(app.name, :name)}'...")
|
|
94
|
+
|
|
95
|
+
seconds = 0
|
|
96
|
+
@first_time_after_staging_succeeded = true
|
|
97
|
+
|
|
98
|
+
begin
|
|
99
|
+
instances = []
|
|
100
|
+
while true
|
|
101
|
+
if any_instance_flapping?(instances) || seconds == APP_CHECK_LIMIT
|
|
102
|
+
err "Push unsuccessful."
|
|
103
|
+
return
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
begin
|
|
107
|
+
return unless instances = app.instances
|
|
108
|
+
|
|
109
|
+
indented { print_instances_summary(instances) }
|
|
110
|
+
|
|
111
|
+
if all_instances_running?(instances)
|
|
112
|
+
line "#{c("Push successful! App '#{app.name}' available at http://#{app.host}.#{app.domain}", :good)}"
|
|
113
|
+
return
|
|
114
|
+
end
|
|
115
|
+
rescue JFoundry::NotStaged
|
|
116
|
+
print (".")
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
sleep 1
|
|
120
|
+
seconds += 1
|
|
121
|
+
end
|
|
122
|
+
rescue JFoundry::StagingError
|
|
123
|
+
err "Application failed to stage"
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def all_instances_running?(instances)
|
|
128
|
+
instances.all? { |i| i.state == "RUNNING" }
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def any_instance_flapping?(instances)
|
|
132
|
+
instances.any? { |i| i.state == "FLAPPING" }
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def print_instances_summary(instances)
|
|
136
|
+
|
|
137
|
+
if @first_time_after_staging_succeeded
|
|
138
|
+
line
|
|
139
|
+
@first_time_after_staging_succeeded = false
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
counts = Hash.new { 0 }
|
|
143
|
+
instances.each do |i|
|
|
144
|
+
counts[i.state] += 1
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
states = []
|
|
148
|
+
%w{RUNNING STARTING DOWN FLAPPING}.each do |state|
|
|
149
|
+
if (num = counts[state]) > 0
|
|
150
|
+
states << "#{b(num)} #{c(state.downcase, state_color(state))}"
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
total = instances.count
|
|
155
|
+
running = counts["RUNNING"].to_s.rjust(total.to_s.size)
|
|
156
|
+
|
|
157
|
+
ratio = "#{running}#{d(" of ")}#{total} instances running"
|
|
158
|
+
line "#{ratio} (#{states.join(", ")})"
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|