jdc 0.2.1 → 0.2.2.pre
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.rb +15 -2
- data/lib/jdc/cli.rb +556 -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.rb +103 -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/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/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/manifests/errors.rb +35 -0
- data/lib/manifests/loader.rb +31 -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/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 +371 -210
- data/README.md +0 -102
- data/config/micro/paths.yml +0 -22
- data/config/micro/refresh_ip.rb +0 -20
- data/lib/cli.rb +0 -53
- 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 -300
- 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/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,43 @@
|
|
|
1
|
+
require "jdc/cli/app/base"
|
|
2
|
+
|
|
3
|
+
module JDC::App
|
|
4
|
+
class Apps < Base
|
|
5
|
+
IS_UTF8 = !!(ENV["LC_ALL"] || ENV["LC_CTYPE"] || ENV["LANG"] || "")["UTF-8"].freeze
|
|
6
|
+
|
|
7
|
+
desc "Show app information"
|
|
8
|
+
group :apps
|
|
9
|
+
input :app, :desc => "App to show", :argument => :required,
|
|
10
|
+
:from_given => by_name(:app)
|
|
11
|
+
def app
|
|
12
|
+
app = input[:app]
|
|
13
|
+
|
|
14
|
+
if quiet?
|
|
15
|
+
line app.name
|
|
16
|
+
else
|
|
17
|
+
display_app(app)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def display_app(a)
|
|
22
|
+
status = app_status(a)
|
|
23
|
+
|
|
24
|
+
line "#{c(a.name, :name)}: #{status}"
|
|
25
|
+
|
|
26
|
+
indented do
|
|
27
|
+
start_line "usage: #{b(human_mb(a.memory))}"
|
|
28
|
+
print " #{d(IS_UTF8 ? "\xc3\x97" : "x")} #{b(a.total_instances)}"
|
|
29
|
+
print " instance#{a.total_instances == 1 ? "" : "s"}"
|
|
30
|
+
|
|
31
|
+
line
|
|
32
|
+
|
|
33
|
+
unless a.urls.empty?
|
|
34
|
+
line "urls: #{a.urls.collect { |u| b(u) }.join(", ")}"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
unless a.services.empty?
|
|
38
|
+
line "services: #{a.services.collect { |s| b(s.name) }.join(", ")}"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
require "jdc/cli/app/base"
|
|
2
|
+
|
|
3
|
+
module JDC::App
|
|
4
|
+
class Apps < Base
|
|
5
|
+
desc "List your applications"
|
|
6
|
+
group :apps
|
|
7
|
+
input :space, :desc => "Show apps in given space",
|
|
8
|
+
:default => proc { client.current_space },
|
|
9
|
+
:from_given => by_name(:space)
|
|
10
|
+
input :name, :desc => "Filter by name regexp"
|
|
11
|
+
input :url, :desc => "Filter by url regexp"
|
|
12
|
+
input :full, :desc => "Verbose output format", :default => false
|
|
13
|
+
def apps
|
|
14
|
+
if space = input[:space]
|
|
15
|
+
begin
|
|
16
|
+
space.summarize!
|
|
17
|
+
rescue JFoundry::APIError
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
apps =
|
|
21
|
+
with_progress("Getting applications in #{c(space.name, :name)}") do
|
|
22
|
+
space.apps
|
|
23
|
+
end
|
|
24
|
+
else
|
|
25
|
+
apps =
|
|
26
|
+
with_progress("Getting applications") do
|
|
27
|
+
client.apps(:depth => 2)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
line unless quiet?
|
|
32
|
+
|
|
33
|
+
if apps.empty? and !quiet?
|
|
34
|
+
line "No applications."
|
|
35
|
+
return
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
apps.reject! do |a|
|
|
39
|
+
!app_matches?(a, input)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
apps = apps.sort_by(&:name)
|
|
43
|
+
|
|
44
|
+
if input[:full]
|
|
45
|
+
spaced(apps) do |a|
|
|
46
|
+
invoke :app, :app => a
|
|
47
|
+
end
|
|
48
|
+
elsif quiet?
|
|
49
|
+
apps.each do |a|
|
|
50
|
+
line a.name
|
|
51
|
+
end
|
|
52
|
+
else
|
|
53
|
+
display_apps_table(apps)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def display_apps_table(apps)
|
|
58
|
+
table(
|
|
59
|
+
["name", "status", "usage", "url"],
|
|
60
|
+
apps.collect { |a|
|
|
61
|
+
[ c(a.name, :name),
|
|
62
|
+
app_status(a),
|
|
63
|
+
"#{a.total_instances} x #{human_mb(a.memory)}",
|
|
64
|
+
if a.urls.empty?
|
|
65
|
+
d("none")
|
|
66
|
+
elsif a.urls.size == 1
|
|
67
|
+
a.url
|
|
68
|
+
else
|
|
69
|
+
"#{a.url}, ..."
|
|
70
|
+
end
|
|
71
|
+
]
|
|
72
|
+
})
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def app_matches?(a, options)
|
|
76
|
+
if name = options[:name]
|
|
77
|
+
return false if a.name !~ /#{name}/
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
if url = options[:url]
|
|
81
|
+
return false if a.urls.none? { |u| u =~ /#{url}/ }
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
true
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
require "jdc/cli"
|
|
2
|
+
|
|
3
|
+
module JDC
|
|
4
|
+
module App
|
|
5
|
+
class Base < CLI
|
|
6
|
+
include LoginRequirements
|
|
7
|
+
|
|
8
|
+
# choose the right color for app/instance state
|
|
9
|
+
def state_color(s)
|
|
10
|
+
case s
|
|
11
|
+
when "STARTING"
|
|
12
|
+
:neutral
|
|
13
|
+
when "STARTED", "RUNNING"
|
|
14
|
+
:good
|
|
15
|
+
when "DOWN"
|
|
16
|
+
:bad
|
|
17
|
+
when "FLAPPING"
|
|
18
|
+
:error
|
|
19
|
+
when "N/A"
|
|
20
|
+
:unknown
|
|
21
|
+
else
|
|
22
|
+
:warning
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def app_status(a)
|
|
27
|
+
health = a.health
|
|
28
|
+
|
|
29
|
+
if a.debug_mode == "suspend" && health == "0%"
|
|
30
|
+
c("suspended", :neutral)
|
|
31
|
+
else
|
|
32
|
+
c(health.downcase, state_color(health))
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def memory_choices
|
|
37
|
+
[128, 256, 512, 1024].map{|n| human_mb(n)}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def human_mb(num)
|
|
41
|
+
human_size(num * 1024 * 1024, 0)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def human_size(num, precision = 1)
|
|
45
|
+
sizes = %w(G M K)
|
|
46
|
+
sizes.each.with_index do |suf, i|
|
|
47
|
+
pow = sizes.size - i
|
|
48
|
+
unit = 1024.0 ** pow
|
|
49
|
+
if num >= unit
|
|
50
|
+
return format("%.#{precision}f%s", num / unit, suf)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
format("%.#{precision}fB", num)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def megabytes(str)
|
|
58
|
+
if str =~ /T$/i
|
|
59
|
+
str.to_i * 1024 * 1024
|
|
60
|
+
elsif str =~ /G$/i
|
|
61
|
+
str.to_i * 1024
|
|
62
|
+
elsif str =~ /M$/i
|
|
63
|
+
str.to_i
|
|
64
|
+
elsif str =~ /K$/i
|
|
65
|
+
str.to_i / 1024
|
|
66
|
+
else # assume megabytes
|
|
67
|
+
str.to_i
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
require "set"
|
|
2
|
+
|
|
3
|
+
require "jdc/cli/app/base"
|
|
4
|
+
|
|
5
|
+
module JDC::App
|
|
6
|
+
class Delete < Base
|
|
7
|
+
desc "Delete an application"
|
|
8
|
+
group :apps, :manage
|
|
9
|
+
input :apps, :desc => "Applications to delete", :argument => :splat,
|
|
10
|
+
:singular => :app, :from_given => by_name(:app)
|
|
11
|
+
input :routes, :desc => "Delete associated routes", :default => false
|
|
12
|
+
input :delete_orphaned, :desc => "Delete orphaned services",
|
|
13
|
+
:aliases => "-o", :default => proc { force? ? false : interact },
|
|
14
|
+
:forget => true
|
|
15
|
+
input :all, :desc => "Delete all applications", :default => false
|
|
16
|
+
input :really, :type => :boolean, :forget => true, :hidden => true,
|
|
17
|
+
:default => proc { force? || interact }
|
|
18
|
+
def delete
|
|
19
|
+
apps = client.apps
|
|
20
|
+
|
|
21
|
+
if input[:all]
|
|
22
|
+
return unless input[:really, "ALL APPS", :bad]
|
|
23
|
+
|
|
24
|
+
to_delete = apps
|
|
25
|
+
others = []
|
|
26
|
+
else
|
|
27
|
+
to_delete = input[:apps]
|
|
28
|
+
others = apps - to_delete
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
all_services = apps.collect(&:services).flatten
|
|
32
|
+
deleted_app_services = []
|
|
33
|
+
|
|
34
|
+
spaced(to_delete) do |app|
|
|
35
|
+
really = input[:all] || input[:really, app.name, :name]
|
|
36
|
+
next unless really
|
|
37
|
+
|
|
38
|
+
deleted_app_services += app.services
|
|
39
|
+
|
|
40
|
+
with_progress("Deleting #{c(app.name, :name)}") do
|
|
41
|
+
app.routes.collect(&:delete!) if input[:routes]
|
|
42
|
+
app.delete!
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
delete_orphaned_services(
|
|
47
|
+
find_orphaned_services(deleted_app_services, all_services))
|
|
48
|
+
|
|
49
|
+
to_delete
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def find_orphaned_services(deleted, all)
|
|
53
|
+
orphaned = []
|
|
54
|
+
|
|
55
|
+
leftover = all.dup
|
|
56
|
+
deleted.each do |svc|
|
|
57
|
+
leftover.slice!(leftover.index(svc))
|
|
58
|
+
orphaned << svc unless leftover.include?(svc)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# clear out the relationships as the apps are now deleted
|
|
62
|
+
orphaned.each(&:invalidate!)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def delete_orphaned_services(orphans)
|
|
66
|
+
return if orphans.empty?
|
|
67
|
+
|
|
68
|
+
line unless quiet? || force?
|
|
69
|
+
|
|
70
|
+
orphans.select { |o| input[:delete_orphaned, o] }.each do |service|
|
|
71
|
+
# TODO: splat
|
|
72
|
+
invoke :delete_service, :service => service, :really => true
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def ask_apps
|
|
79
|
+
apps = client.apps
|
|
80
|
+
fail "No applications." if apps.empty?
|
|
81
|
+
|
|
82
|
+
[ask("Delete which application?", :choices => apps.sort_by(&:name),
|
|
83
|
+
:display => proc(&:name))]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def ask_really(name, color)
|
|
87
|
+
ask("Really delete #{c(name, color)}?", :default => false)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def ask_delete_orphaned(service)
|
|
91
|
+
ask("Delete orphaned service #{c(service.name, :name)}?",
|
|
92
|
+
:default => false)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
require "jdc/cli/app/base"
|
|
2
|
+
|
|
3
|
+
module JDC::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
|
|
9
|
+
input :app, :desc => "Application to inspect the environment of",
|
|
10
|
+
:argument => true, :from_given => by_name(:app)
|
|
11
|
+
def env
|
|
12
|
+
app = input[:app]
|
|
13
|
+
|
|
14
|
+
vars =
|
|
15
|
+
with_progress("Getting env for #{c(app.name, :name)}") do |s|
|
|
16
|
+
app.env
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
line unless quiet?
|
|
20
|
+
|
|
21
|
+
vars.each do |name, val|
|
|
22
|
+
line "#{c(name, :name)}: #{val}"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
desc "Set an environment variable"
|
|
27
|
+
group :apps, :info
|
|
28
|
+
input :app, :desc => "Application to set the variable for",
|
|
29
|
+
:argument => true, :from_given => by_name(:app)
|
|
30
|
+
input :name, :desc => "Variable name", :argument => true
|
|
31
|
+
input :value, :desc => "Variable value", :argument => :optional
|
|
32
|
+
input :restart, :desc => "Restart app after updating?", :default => true
|
|
33
|
+
def set_env
|
|
34
|
+
app = input[:app]
|
|
35
|
+
name = input[:name]
|
|
36
|
+
|
|
37
|
+
if value = input[:value]
|
|
38
|
+
name = input[:name]
|
|
39
|
+
elsif name["="]
|
|
40
|
+
name, value = name.split("=")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
unless name =~ VALID_ENV_VAR
|
|
44
|
+
fail "Invalid variable name; must match #{VALID_ENV_VAR.inspect}"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
with_progress("Updating #{c(app.name, :name)}") do
|
|
48
|
+
app.env[name] = value
|
|
49
|
+
app.update!
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
if app.started? && input[:restart]
|
|
53
|
+
invoke :restart, :app => app
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
desc "Remove an environment variable"
|
|
59
|
+
group :apps, :info
|
|
60
|
+
input :app, :desc => "Application to set the variable for",
|
|
61
|
+
:argument => true, :from_given => by_name(:app)
|
|
62
|
+
input :name, :desc => "Variable name", :argument => true
|
|
63
|
+
input :restart, :desc => "Restart app after updating?", :default => true
|
|
64
|
+
def unset_env
|
|
65
|
+
app = input[:app]
|
|
66
|
+
name = input[:name]
|
|
67
|
+
|
|
68
|
+
with_progress("Updating #{c(app.name, :name)}") do
|
|
69
|
+
app.env.delete(name)
|
|
70
|
+
app.update!
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
if app.started? && input[:restart]
|
|
74
|
+
invoke :restart, :app => app
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require "jdc/cli/app/base"
|
|
2
|
+
|
|
3
|
+
module JDC::App
|
|
4
|
+
class Events < Base
|
|
5
|
+
desc "Display application events"
|
|
6
|
+
group :apps, :info
|
|
7
|
+
input :app, :desc => "Application to get the events for",
|
|
8
|
+
:argument => true, :from_given => by_name(:app)
|
|
9
|
+
def events
|
|
10
|
+
app = input[:app]
|
|
11
|
+
|
|
12
|
+
events =
|
|
13
|
+
with_progress("Getting events for #{c(app.name, :name)}") do
|
|
14
|
+
format_events(app.events)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
line unless quiet?
|
|
18
|
+
table(%w{time instance\ index description exit\ status}, events)
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def sort_events(events)
|
|
25
|
+
events.sort_by { |event| DateTime.parse(event.timestamp) }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def format_events(events)
|
|
29
|
+
sort_events(events).map do |event|
|
|
30
|
+
[event.timestamp,
|
|
31
|
+
c(event.instance_index.to_s, :warning),
|
|
32
|
+
event.exit_description,
|
|
33
|
+
format_status(event)]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def format_status(event)
|
|
38
|
+
if event.exit_status == 0
|
|
39
|
+
c("Success (#{event.exit_status})", :good)
|
|
40
|
+
else
|
|
41
|
+
c("Failure (#{event.exit_status})", :bad)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
require "thread"
|
|
2
|
+
require "jdc/cli/app/base"
|
|
3
|
+
|
|
4
|
+
module JDC::App
|
|
5
|
+
class Files < Base
|
|
6
|
+
desc "Print out an app's file contents"
|
|
7
|
+
group :apps, :info
|
|
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 JFoundry::NotFound
|
|
31
|
+
fail "Invalid path #{b(path)} for app #{b(app.name)}"
|
|
32
|
+
rescue JFoundry::FileError => e
|
|
33
|
+
fail e.description
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
desc "Examine an app's files"
|
|
37
|
+
group :apps, :info
|
|
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 JFoundry::NotFound
|
|
59
|
+
fail "Invalid path #{b(path)} for app #{b(app.name)}"
|
|
60
|
+
rescue JFoundry::FileError => e
|
|
61
|
+
fail e.description
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
desc "Stream an app's file contents"
|
|
65
|
+
group :apps, :info
|
|
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 JFoundry::NotFound
|
|
108
|
+
fail "Invalid path #{b(path)} for app #{b(app.name)}"
|
|
109
|
+
rescue JFoundry::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
|