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.
Files changed (151) hide show
  1. data/LICENSE +1277 -24
  2. data/Rakefile +13 -0
  3. data/bin/jdc +12 -2
  4. data/lib/admin/README.md +15 -0
  5. data/lib/admin/curl.rb +60 -0
  6. data/lib/admin/guid.rb +89 -0
  7. data/lib/admin/plugin.rb +6 -0
  8. data/lib/admin/service_auth_token.rb +94 -0
  9. data/lib/admin/service_broker/add.rb +47 -0
  10. data/lib/admin/service_broker/service_brokers.rb +24 -0
  11. data/lib/admin/set_quota.rb +44 -0
  12. data/lib/console/README.md +8 -0
  13. data/lib/console/console.rb +187 -0
  14. data/lib/console/plugin.rb +33 -0
  15. data/lib/jdc/cli/app/app.rb +43 -0
  16. data/lib/jdc/cli/app/apps.rb +87 -0
  17. data/lib/jdc/cli/app/base.rb +72 -0
  18. data/lib/jdc/cli/app/delete.rb +95 -0
  19. data/lib/jdc/cli/app/deprecated.rb +11 -0
  20. data/lib/jdc/cli/app/env.rb +78 -0
  21. data/lib/jdc/cli/app/events.rb +45 -0
  22. data/lib/jdc/cli/app/files.rb +137 -0
  23. data/lib/jdc/cli/app/health.rb +26 -0
  24. data/lib/jdc/cli/app/instances.rb +53 -0
  25. data/lib/jdc/cli/app/logs.rb +76 -0
  26. data/lib/jdc/cli/app/push/create.rb +108 -0
  27. data/lib/jdc/cli/app/push/interactions.rb +86 -0
  28. data/lib/jdc/cli/app/push/sync.rb +57 -0
  29. data/lib/jdc/cli/app/push.rb +103 -0
  30. data/lib/jdc/cli/app/rename.rb +35 -0
  31. data/lib/jdc/cli/app/restart.rb +31 -0
  32. data/lib/jdc/cli/app/scale.rb +63 -0
  33. data/lib/jdc/cli/app/start.rb +161 -0
  34. data/lib/jdc/cli/app/stats.rb +67 -0
  35. data/lib/jdc/cli/app/stop.rb +27 -0
  36. data/lib/jdc/cli/domain/base.rb +9 -0
  37. data/lib/jdc/cli/domain/domains.rb +40 -0
  38. data/lib/jdc/cli/domain/map.rb +55 -0
  39. data/lib/jdc/cli/domain/unmap.rb +56 -0
  40. data/lib/jdc/cli/help.rb +15 -0
  41. data/lib/jdc/cli/interactive.rb +105 -0
  42. data/lib/jdc/cli/login_requirements.rb +15 -0
  43. data/lib/jdc/cli/organization/base.rb +14 -0
  44. data/lib/jdc/cli/organization/create.rb +37 -0
  45. data/lib/jdc/cli/organization/delete.rb +63 -0
  46. data/lib/jdc/cli/organization/org.rb +45 -0
  47. data/lib/jdc/cli/organization/orgs.rb +30 -0
  48. data/lib/jdc/cli/organization/rename.rb +37 -0
  49. data/lib/jdc/cli/populators/base.rb +16 -0
  50. data/lib/jdc/cli/populators/organization.rb +32 -0
  51. data/lib/jdc/cli/populators/populator_methods.rb +64 -0
  52. data/lib/jdc/cli/populators/space.rb +33 -0
  53. data/lib/jdc/cli/populators/target.rb +13 -0
  54. data/lib/jdc/cli/route/base.rb +9 -0
  55. data/lib/jdc/cli/route/delete.rb +28 -0
  56. data/lib/jdc/cli/route/map.rb +68 -0
  57. data/lib/jdc/cli/route/routes.rb +26 -0
  58. data/lib/jdc/cli/route/unmap.rb +56 -0
  59. data/lib/jdc/cli/service/base.rb +9 -0
  60. data/lib/jdc/cli/service/bind.rb +44 -0
  61. data/lib/jdc/cli/service/create.rb +159 -0
  62. data/lib/jdc/cli/service/delete.rb +83 -0
  63. data/lib/jdc/cli/service/rename.rb +36 -0
  64. data/lib/jdc/cli/service/service.rb +42 -0
  65. data/lib/jdc/cli/service/service_instance_helper.rb +99 -0
  66. data/lib/jdc/cli/service/services.rb +111 -0
  67. data/lib/jdc/cli/service/unbind.rb +37 -0
  68. data/lib/jdc/cli/space/base.rb +29 -0
  69. data/lib/jdc/cli/space/create.rb +67 -0
  70. data/lib/jdc/cli/space/delete.rb +56 -0
  71. data/lib/jdc/cli/space/rename.rb +38 -0
  72. data/lib/jdc/cli/space/space.rb +66 -0
  73. data/lib/jdc/cli/space/spaces.rb +57 -0
  74. data/lib/jdc/cli/space/switch.rb +19 -0
  75. data/lib/jdc/cli/start/base.rb +41 -0
  76. data/lib/jdc/cli/start/colors.rb +13 -0
  77. data/lib/jdc/cli/start/target.rb +50 -0
  78. data/lib/jdc/cli/start/target_prettifier.rb +17 -0
  79. data/lib/jdc/cli/start/targets.rb +16 -0
  80. data/lib/jdc/cli/user/base.rb +30 -0
  81. data/lib/jdc/cli/user/create.rb +52 -0
  82. data/lib/jdc/cli/user/passwd.rb +37 -0
  83. data/lib/jdc/cli/user/register.rb +43 -0
  84. data/lib/jdc/cli/user/users.rb +32 -0
  85. data/lib/jdc/cli.rb +544 -0
  86. data/lib/jdc/constants.rb +11 -0
  87. data/lib/jdc/errors.rb +19 -0
  88. data/lib/jdc/object_extensions.rb +15 -0
  89. data/lib/jdc/plugin.rb +56 -0
  90. data/lib/jdc/spacing.rb +89 -0
  91. data/lib/jdc/spec_helper.rb +1 -0
  92. data/lib/jdc/test_support.rb +6 -0
  93. data/lib/jdc/version.rb +3 -0
  94. data/lib/jdc.rb +15 -2
  95. data/lib/manifests/errors.rb +35 -0
  96. data/lib/manifests/loader/builder.rb +39 -0
  97. data/lib/manifests/loader/normalizer.rb +145 -0
  98. data/lib/manifests/loader/resolver.rb +79 -0
  99. data/lib/manifests/loader.rb +31 -0
  100. data/lib/manifests/manifests.rb +344 -0
  101. data/lib/manifests/plugin.rb +140 -0
  102. data/lib/micro/README.md +9 -0
  103. data/lib/micro/errors.rb +4 -0
  104. data/lib/{jdc → micro}/micro.rb +15 -15
  105. data/lib/micro/plugin.rb +197 -0
  106. data/lib/micro/switcher/base.rb +79 -0
  107. data/lib/{jdc/micro → micro}/switcher/darwin.rb +5 -3
  108. data/lib/{jdc/micro → micro}/switcher/dummy.rb +1 -1
  109. data/lib/micro/switcher/linux.rb +16 -0
  110. data/lib/{jdc/micro → micro}/switcher/windows.rb +5 -5
  111. data/lib/{jdc/micro → micro}/vmrun.rb +26 -19
  112. data/lib/tasks/gem_release.rake +42 -0
  113. data/lib/tunnel/README.md +29 -0
  114. data/{config → lib/tunnel/config}/clients.yml +2 -2
  115. data/lib/tunnel/helper-app/Gemfile +10 -0
  116. data/lib/tunnel/helper-app/Gemfile.lock +48 -0
  117. data/{caldecott_helper → lib/tunnel/helper-app}/server.rb +5 -5
  118. data/lib/tunnel/plugin.rb +183 -0
  119. data/lib/tunnel/tunnel.rb +295 -0
  120. metadata +319 -89
  121. data/README.md +0 -102
  122. data/config/micro/paths.yml +0 -22
  123. data/config/micro/refresh_ip.rb +0 -20
  124. data/lib/cli/commands/admin.rb +0 -58
  125. data/lib/cli/commands/apps.rb +0 -1129
  126. data/lib/cli/commands/base.rb +0 -228
  127. data/lib/cli/commands/manifest.rb +0 -56
  128. data/lib/cli/commands/micro.rb +0 -115
  129. data/lib/cli/commands/misc.rb +0 -126
  130. data/lib/cli/commands/services.rb +0 -178
  131. data/lib/cli/commands/user.rb +0 -14
  132. data/lib/cli/config.rb +0 -173
  133. data/lib/cli/console_helper.rb +0 -170
  134. data/lib/cli/core_ext.rb +0 -122
  135. data/lib/cli/errors.rb +0 -19
  136. data/lib/cli/frameworks.rb +0 -265
  137. data/lib/cli/manifest_helper.rb +0 -302
  138. data/lib/cli/runner.rb +0 -505
  139. data/lib/cli/services_helper.rb +0 -84
  140. data/lib/cli/tunnel_helper.rb +0 -332
  141. data/lib/cli/usage.rb +0 -86
  142. data/lib/cli/version.rb +0 -7
  143. data/lib/cli/zip_util.rb +0 -77
  144. data/lib/cli.rb +0 -53
  145. data/lib/jdc/client.rb +0 -457
  146. data/lib/jdc/const.rb +0 -25
  147. data/lib/jdc/micro/switcher/base.rb +0 -97
  148. data/lib/jdc/micro/switcher/linux.rb +0 -16
  149. data/lib/jdc/signature/version.rb +0 -27
  150. data/lib/jdc/signer.rb +0 -13
  151. data/lib/jdc/timer.rb +0 -12
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require "rake"
2
+ require "rspec/core/rake_task"
3
+ Dir.glob("lib/tasks/**/*").sort.each { |ext| load(ext) }
4
+
5
+ specfile, _ = Dir["*.gemspec"]
6
+ SPEC = Gem::Specification.load(specfile)
7
+ CURRENT_VERSION = SPEC.version.to_s.freeze
8
+
9
+ RSpec::Core::RakeTask.new(:spec)
10
+ task :default => :spec
11
+
12
+ # looking for a way to push gems? check out the new frontend-release git repo!
13
+ # git@github.com:pivotal-vmware/frontend-release.git
data/bin/jdc CHANGED
@@ -1,6 +1,16 @@
1
1
  #!/usr/bin/env ruby
2
+ # vim: ft=ruby
2
3
 
3
- require File.expand_path('../../lib/cli', __FILE__)
4
+ require "rubygems"
4
5
 
5
- JDC::Cli::Runner.run(ARGV.dup)
6
+ require "jdc"
7
+ require "jdc/plugin"
6
8
 
9
+ $stdout.sync = true
10
+
11
+ JDC::Plugin.load_all
12
+ if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new("1.9.3")
13
+ warn "ERROR: \033[31mRuby version #{RUBY_VERSION} is not supported.\033[0m Please install 1.9.3 or later. (See http://docs.cloudfoundry.com/docs/common/install_ruby.html for more information)"
14
+ exit 1
15
+ end
16
+ JDC::CLI.start(ARGV)
@@ -0,0 +1,15 @@
1
+ ## Admin
2
+ ### Info
3
+ This plugin allows you to make manual HTTP requests to the Jing Dong Foundry REST API.
4
+
5
+ ### Usage
6
+
7
+ ```
8
+ curl MODE PATH HEADERS... Execute a raw request
9
+ guid TYPE [NAME] Obtain guid of an object(s)
10
+ set-quota [QUOTA_DEFINITION] [ORGANIZATION] Change the quota definition for the given (or current) organization.
11
+ service-auth-tokens List service auth tokens
12
+ create-service-auth-token [LABEL] [PROVIDER] Create a service auth token
13
+ update-service-auth-token [SERVICE_AUTH_TOKEN] Update a service auth token
14
+ delete-service-auth-token [SERVICE_AUTH_TOKEN] Delete a service auth token
15
+ ```
data/lib/admin/curl.rb ADDED
@@ -0,0 +1,60 @@
1
+ require "multi_json"
2
+
3
+ require "jdc/cli"
4
+ =begin
5
+ module JDCAdmin
6
+ class Curl < JDC::CLI
7
+ def precondition
8
+ check_target
9
+ end
10
+
11
+ desc "Execute a raw request"
12
+ group :admin
13
+ input :mode, :argument => :required, :desc => "Request mode (Get/Put/etc.)"
14
+ input :path, :argument => :required, :desc => "Request path"
15
+ input :headers, :argument => :splat, :desc => "Headers (i.e. Foo: bar)"
16
+ input :body, :alias => "-b", :desc => "Request body"
17
+ def curl
18
+ mode = input[:mode].upcase
19
+ path = input[:path]
20
+ body = input[:body]
21
+
22
+ headers = {}
23
+ input[:headers].each do |h|
24
+ k, v = h.split(/\s*:\s*/, 2)
25
+ headers[k.downcase] = v
26
+ end
27
+
28
+ content = headers["content-type"]
29
+ accept = headers["accept"]
30
+
31
+ content ||= :json if body
32
+ accept ||= :json unless %w(DELETE HEAD).include?(mode)
33
+
34
+ req, res =
35
+ client.base.rest_client.request(
36
+ mode,
37
+ remove_leading_slash(path),
38
+ :headers => headers,
39
+ :accept => accept,
40
+ :payload => body,
41
+ :content => body && content)
42
+
43
+ body = res[:body]
44
+
45
+ type = res[:headers]["content-type"]
46
+
47
+ if type && type.include?("application/json")
48
+ json = MultiJson.load(body)
49
+ puts MultiJson.dump(json, :pretty => true)
50
+ else
51
+ puts body
52
+ end
53
+ end
54
+
55
+ def remove_leading_slash(path)
56
+ path.sub(%r{^/}, '')
57
+ end
58
+ end
59
+ end
60
+ =end
data/lib/admin/guid.rb ADDED
@@ -0,0 +1,89 @@
1
+ require "jdc/cli"
2
+
3
+ module JDCAdmin
4
+ class Guid < JDC::CLI
5
+ def precondition
6
+ check_target
7
+ end
8
+
9
+ desc "Obtain guid of an object(s)"
10
+ group :admin
11
+ input :type, :argument => :required, :desc => "Object type (e.g. org, space, app, domain, ...)"
12
+ input :name, :argument => :optional, :desc => "Object name (e.g. some-app, ...)"
13
+ def guid
14
+ type = expand_type(input[:type])
15
+ name = input[:name]
16
+
17
+ _, res = client.base.rest_client.request("GET", api_path(type, name))
18
+
19
+ puts "Listing #{type} for '#{name}'...\n\n"
20
+ puts_response(res[:body])
21
+ end
22
+
23
+ private
24
+
25
+ def api_path(type, name)
26
+ "".tap do |url|
27
+ url << "v2/#{type}?"
28
+ url << "q=name:#{name}" if name
29
+ end
30
+ end
31
+
32
+ EXPANDED_TYPES = %w(
33
+ organizations
34
+ spaces
35
+ domains
36
+ routes
37
+ apps
38
+ services
39
+ service_instances
40
+ users
41
+ )
42
+
43
+ def expand_type(type)
44
+ EXPANDED_TYPES.detect do |expanded_type|
45
+ expanded_type.start_with?(type)
46
+ end || type
47
+ end
48
+
49
+ def puts_response(body)
50
+ # passing nil to load causes segfault
51
+ hash = MultiJson.load(body || "{}") rescue {}
52
+
53
+ puts_pagination(*hash.values_at("total_results", "total_pages"))
54
+ puts_resources(hash["resources"])
55
+ end
56
+
57
+ def puts_pagination(results, pages)
58
+ if results.nil?
59
+ puts "Unexpected response."
60
+ elsif results == 0
61
+ puts "No results."
62
+ else
63
+ puts "Found #{results} results on #{pages} pages. First page:"
64
+ end
65
+ end
66
+
67
+ def puts_resources(resources)
68
+ resources ||= []
69
+
70
+ sorted_resources = \
71
+ resources.sort_by { |r| [r["entity"]["name"].downcase] }
72
+
73
+ max_name_size = \
74
+ resources.map { |r| r["entity"]["name"].size }.max
75
+
76
+ sorted_resources.each_with_index do |resource, i|
77
+ puts_resource(resource, :max_name_size => max_name_size)
78
+ puts "---" if i % 3 == 2
79
+ end
80
+ end
81
+
82
+ def puts_resource(resource, opts={})
83
+ puts [
84
+ resource["entity"]["name"].ljust(opts[:max_name_size] + 2),
85
+ resource["metadata"]["guid"],
86
+ ].join
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,6 @@
1
+ require "admin/curl"
2
+ require "admin/guid"
3
+ require "admin/set_quota"
4
+ #require "admin/service_auth_token"
5
+ require "admin/service_broker/add"
6
+ require "admin/service_broker/service_brokers"
@@ -0,0 +1,94 @@
1
+ require "jdc/cli"
2
+
3
+ module JDCAdmin
4
+ class ServiceAuthToken < JDC::CLI
5
+ def precondition
6
+ unless File.exists? target_file
7
+ fail "Please select a target with 'jdc target'."
8
+ end
9
+
10
+ #check_key
11
+ #unless client.logged_in?
12
+ # fail "Please log in with 'jdc login'."
13
+ #end
14
+ end
15
+
16
+
17
+ desc "List service auth tokens"
18
+ group :admin
19
+ def service_auth_tokens
20
+ spaced(client.service_auth_tokens) do |t|
21
+ line "#{c(t.label, :name)}:"
22
+
23
+ indented do
24
+ line "guid: #{t.guid}"
25
+ line "provider: #{t.provider}"
26
+ end
27
+ end
28
+ end
29
+
30
+
31
+ desc "Create a service auth token"
32
+ group :admin
33
+ input(:label, :argument => :optional, :desc => "Auth token label") {
34
+ ask("Label")
35
+ }
36
+ input :provider, :argument => :optional, :default => "core",
37
+ :desc => "Auth token provider"
38
+ input(:token, :desc => "Auth token value") {
39
+ ask("Token")
40
+ }
41
+ def create_service_auth_token
42
+ sat = client.service_auth_token
43
+ sat.label = input[:label]
44
+ sat.provider = input[:provider]
45
+ sat.token = input[:token]
46
+
47
+ with_progress("Creating service auth token") do
48
+ sat.create!
49
+ end
50
+ end
51
+
52
+
53
+ desc "Update a service auth token"
54
+ group :admin
55
+ input(:service_auth_token, :argument => :optional,
56
+ :from_given => proc { |guid| client.service_auth_token(guid) },
57
+ :desc => "Auth token to delete") {
58
+ tokens = client.service_auth_tokens
59
+ fail "No tokens!" if tokens.empty?
60
+
61
+ ask("Which token?", :choices => tokens, :display => proc(&:label))
62
+ }
63
+ input(:token, :desc => "Auth token value") {
64
+ ask("Token")
65
+ }
66
+ def update_service_auth_token
67
+ sat = input[:service_auth_token]
68
+ sat.token = input[:token]
69
+
70
+ with_progress("Updating token #{c(sat.label, :name)}") do
71
+ sat.update!
72
+ end
73
+ end
74
+
75
+
76
+ desc "Delete a service auth token"
77
+ group :admin
78
+ input(:service_auth_token, :argument => :optional,
79
+ :from_given => proc { |guid| client.service_auth_token(guid) },
80
+ :desc => "Auth token to delete") {
81
+ tokens = client.service_auth_tokens
82
+ fail "No tokens!" if tokens.empty?
83
+
84
+ ask("Which token?", :choices => tokens, :display => proc(&:label))
85
+ }
86
+ def delete_service_auth_token
87
+ sat = input[:service_auth_token]
88
+
89
+ with_progress("Deleting token #{c(sat.label, :name)}") do
90
+ sat.delete!
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,47 @@
1
+ require "jdc/cli"
2
+ =begin
3
+ module JDCAdmin::ServiceBroker
4
+ class Add < JDC::CLI
5
+ def precondition
6
+ check_target
7
+ end
8
+
9
+ desc "Add a Service Broker."
10
+ group :admin
11
+ input :name, :argument => :optional,
12
+ :desc => "Broker name"
13
+ input :url,
14
+ :desc => "Broker URL"
15
+ input :token,
16
+ :desc => "Broker token"
17
+
18
+ def add_service_broker
19
+ broker = client.service_broker
20
+
21
+ broker.name = input[:name]
22
+ finalize
23
+ broker.broker_url = input[:url]
24
+ finalize
25
+ broker.token = input[:token]
26
+ finalize
27
+
28
+ with_progress("") do
29
+ broker.create!
30
+ end
31
+ end
32
+
33
+ private
34
+ def ask_name
35
+ ask("Name")
36
+ end
37
+
38
+ def ask_url
39
+ ask("URL")
40
+ end
41
+
42
+ def ask_token
43
+ ask("Token")
44
+ end
45
+ end
46
+ end
47
+ =end
@@ -0,0 +1,24 @@
1
+ require "jdc/cli"
2
+ =begin
3
+ module JDCAdmin::ServiceBroker
4
+ class ServiceBrokers < JDC::CLI
5
+ def precondition
6
+ check_target
7
+ end
8
+
9
+ desc "List Registered Service Brokers."
10
+ group :admin
11
+
12
+ def service_brokers
13
+ brokers = client.service_brokers
14
+ table(
15
+ %w(name url),
16
+ brokers.collect { |broker|
17
+ [c(broker.name, :name), broker.broker_url]
18
+ }
19
+ )
20
+ end
21
+
22
+ end
23
+ end
24
+ =end
@@ -0,0 +1,44 @@
1
+ require "jdc/cli"
2
+
3
+ module JDCAdmin
4
+ class SetQuota < JDC::CLI
5
+ def precondition
6
+ check_target
7
+ end
8
+
9
+ desc "Change the quota definition for the given (or current) organization."
10
+ group :admin
11
+ input :quota_definition, :argument => :optional,
12
+ :from_given => by_name(:quota_definition),
13
+ :desc => "Quota definition to set on the organization"
14
+ input :organization, :aliases => %w(org o), :argument => :optional,
15
+ :from_given => by_name(:organization),
16
+ :default => proc { client.current_organization || interact },
17
+ :desc => "Organization to update"
18
+ def set_quota
19
+ org = input[:organization]
20
+ quota = input[:quota_definition]
21
+
22
+ with_progress(<<MESSAGE.chomp) do
23
+ Setting quota of #{c(org.name, :name)} to #{c(quota.name, :name)}
24
+ MESSAGE
25
+ org.quota_definition = quota
26
+ org.update!
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def ask_quota_definition
33
+ ask("Quota",
34
+ :choices => client.quota_definitions,
35
+ :display => proc(&:name))
36
+ end
37
+
38
+ def ask_organization
39
+ ask("Organization",
40
+ :choices => client.organizations,
41
+ :display => proc(&:name))
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,8 @@
1
+ ## Console
2
+ ### Info
3
+ This plugin lets you connect to a Jing Dong Foundry application via telnet.
4
+
5
+ ### Usage
6
+ ```
7
+ console APP Open a console connected to your app
8
+ ```
@@ -0,0 +1,187 @@
1
+ require "net/telnet"
2
+ require "readline"
3
+
4
+ require "tunnel/tunnel"
5
+
6
+ class JDCConsole < JDCTunnel
7
+ def initialize(client, app, port = 10000)
8
+ @client = client
9
+ @app = app
10
+ @port = port
11
+ end
12
+
13
+ def get_connection_info(auth)
14
+ instances = @app.instances
15
+ if instances.empty?
16
+ raise "App has no running instances; try starting it."
17
+ end
18
+
19
+ unless console = instances[0].console
20
+ raise "App does not have console access; try restarting it."
21
+ end
22
+
23
+ { "hostname" => console[:ip],
24
+ "port" => console[:port]
25
+ }
26
+ end
27
+
28
+ def get_credentials
29
+ YAML.load(@app.file("app", "jdc-rails-console", ".consoleaccess"))
30
+ end
31
+
32
+ def start_console
33
+ prompt = login
34
+
35
+ init_readline
36
+
37
+ run_console prompt
38
+ end
39
+
40
+ def login(auth = get_credentials)
41
+ if !auth["username"] || !auth["password"]
42
+ raise "Unable to verify console credentials."
43
+ end
44
+
45
+ @telnet = telnet_client
46
+
47
+ prompt = nil
48
+ err_msg = "Login attempt timed out."
49
+
50
+ 5.times do
51
+ begin
52
+ results = @telnet.login(
53
+ "Name" => auth["username"],
54
+ "Password" => auth["password"])
55
+
56
+ lines = results.sub("Login: Password: ", "").split("\n")
57
+
58
+ last_line = lines.pop
59
+
60
+ if last_line =~ /[$%#>] \z/n
61
+ prompt = last_line
62
+ elsif last_line =~ /Login failed/
63
+ err_msg = last_line
64
+ end
65
+
66
+ break
67
+
68
+ rescue TimeoutError
69
+ sleep 1
70
+
71
+ rescue EOFError
72
+ # This may happen if we login right after app starts
73
+ close_console
74
+ sleep 5
75
+ @telnet = telnet_client
76
+ end
77
+ end
78
+
79
+ unless prompt
80
+ close_console
81
+ raise err_msg
82
+ end
83
+
84
+ prompt
85
+ end
86
+
87
+ private
88
+
89
+ def init_readline
90
+ if Readline.respond_to?("basic_word_break_characters=")
91
+ Readline.basic_word_break_characters= " \t\n`><=;|&{("
92
+ end
93
+
94
+ Readline.completion_append_character = nil
95
+
96
+ # Assumes that sending a String ending with tab will return a non-empty
97
+ # String of comma-separated completion options, terminated by a new line
98
+ # For example, "app.\t" might result in "to_s,nil?,etc\n"
99
+ Readline.completion_proc = proc do |s|
100
+ console_tab_completion_data(s)
101
+ end
102
+ end
103
+
104
+ def run_console(prompt)
105
+ prev = trap("INT") { |x| exit_console; prev.call(x); exit }
106
+ prev = trap("TERM") { |x| exit_console; prev.call(x); exit }
107
+
108
+ loop do
109
+ cmd = readline_with_history(prompt)
110
+
111
+ if cmd == nil
112
+ exit_console
113
+ break
114
+ end
115
+
116
+ prompt = send_console_command_display_results(cmd, prompt)
117
+ end
118
+ end
119
+
120
+ def readline_with_history(prompt)
121
+ line = Readline::readline(prompt)
122
+
123
+ return if line == nil || line == 'quit' || line == 'exit'
124
+
125
+ if line !~ /^\s*$/ && Readline::HISTORY.to_a.last != line
126
+ Readline::HISTORY.push(line)
127
+ end
128
+
129
+ line
130
+ end
131
+
132
+ def send_console_command_display_results(cmd, prompt)
133
+ begin
134
+ lines = send_console_command cmd
135
+
136
+ # Assumes the last line is a prompt
137
+ prompt = lines.pop
138
+
139
+ lines.each do |line|
140
+ puts line if line != cmd
141
+ end
142
+
143
+ rescue TimeoutError
144
+ puts "Timed out sending command to server."
145
+
146
+ rescue EOFError
147
+ raise "The console connection has been terminated. Perhaps the app was stopped or deleted?"
148
+ end
149
+
150
+ prompt
151
+ end
152
+
153
+ def send_console_command(cmd)
154
+ results = @telnet.cmd(cmd)
155
+ results.split("\n")
156
+ end
157
+
158
+ def exit_console
159
+ @telnet.cmd("String" => "exit", "Timeout" => 1)
160
+ rescue TimeoutError
161
+ # TimeoutError expected, as exit doesn't return anything
162
+ ensure
163
+ close_console
164
+ end
165
+
166
+ def close_console
167
+ @telnet.close
168
+ end
169
+
170
+ def console_tab_completion_data(cmd)
171
+ begin
172
+ results = @telnet.
173
+ cmd("String" => cmd + "\t", "Match" => /\S*\n$/, "Timeout" => 10)
174
+ results.chomp.split(",")
175
+ rescue TimeoutError
176
+ [] #Just return empty results if timeout occurred on tab completion
177
+ end
178
+ end
179
+
180
+ def telnet_client
181
+ Net::Telnet.new(
182
+ "Port" => @port,
183
+ "Prompt" => /[$%#>] \z|Login failed/n,
184
+ "Timeout" => 30,
185
+ "FailEOF" => true)
186
+ end
187
+ end
@@ -0,0 +1,33 @@
1
+ require "jdc/plugin"
2
+ require "console/console"
3
+ =begin
4
+ module JDCConsolePlugin
5
+ class Console < JDC::CLI
6
+ desc "Open a console connected to your app"
7
+ group :apps, :manage
8
+ input :app, :argument => :required, :from_given => by_name("app"),
9
+ :desc => "App to connect to"
10
+ input :port, :default => 10000
11
+ def console
12
+ app = input[:app]
13
+
14
+ console = JDCConsole.new(client, app)
15
+ port = console.pick_port!(input[:port])
16
+
17
+ with_progress("Opening console on port #{c(port, :name)}") do
18
+ console.open!
19
+ console.wait_for_start
20
+ end
21
+
22
+ console.start_console
23
+ end
24
+
25
+ ::ManifestsPlugin.default_to_app_from_manifest :console, true
26
+
27
+ filter(:start, :start_app) do |app|
28
+ app.console = true
29
+ app
30
+ end
31
+ end
32
+ end
33
+ =end
@@ -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