vmc 0.4.0.beta.97 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. data/{vmc-ng/LICENSE → LICENSE} +0 -0
  2. data/{vmc-ng/Rakefile → Rakefile} +0 -0
  3. data/bin/vmc +7 -11
  4. data/{vmc-ng/lib → lib}/vmc.rb +0 -0
  5. data/{vmc-ng/lib → lib}/vmc/cli.rb +0 -0
  6. data/{vmc-ng/lib → lib}/vmc/cli/app/app.rb +0 -0
  7. data/{vmc-ng/lib → lib}/vmc/cli/app/apps.rb +0 -0
  8. data/{vmc-ng/lib → lib}/vmc/cli/app/base.rb +0 -0
  9. data/{vmc-ng/lib → lib}/vmc/cli/app/crashes.rb +0 -0
  10. data/{vmc-ng/lib → lib}/vmc/cli/app/delete.rb +0 -0
  11. data/{vmc-ng/lib → lib}/vmc/cli/app/deprecated.rb +0 -0
  12. data/{vmc-ng/lib → lib}/vmc/cli/app/env.rb +0 -0
  13. data/{vmc-ng/lib → lib}/vmc/cli/app/files.rb +0 -0
  14. data/{vmc-ng/lib → lib}/vmc/cli/app/health.rb +0 -0
  15. data/{vmc-ng/lib → lib}/vmc/cli/app/instances.rb +0 -0
  16. data/{vmc-ng/lib → lib}/vmc/cli/app/logs.rb +0 -0
  17. data/{vmc-ng/lib → lib}/vmc/cli/app/push.rb +0 -0
  18. data/{vmc-ng/lib → lib}/vmc/cli/app/rename.rb +0 -0
  19. data/{vmc-ng/lib → lib}/vmc/cli/app/restart.rb +0 -0
  20. data/{vmc-ng/lib → lib}/vmc/cli/app/routes.rb +0 -0
  21. data/{vmc-ng/lib → lib}/vmc/cli/app/scale.rb +0 -0
  22. data/{vmc-ng/lib → lib}/vmc/cli/app/start.rb +0 -0
  23. data/{vmc-ng/lib → lib}/vmc/cli/app/stats.rb +0 -0
  24. data/{vmc-ng/lib → lib}/vmc/cli/app/stop.rb +0 -0
  25. data/{vmc-ng/lib → lib}/vmc/cli/domain/add_domain.rb +0 -0
  26. data/{vmc-ng/lib → lib}/vmc/cli/domain/base.rb +0 -0
  27. data/{vmc-ng/lib → lib}/vmc/cli/domain/create_domain.rb +0 -0
  28. data/{vmc-ng/lib → lib}/vmc/cli/domain/delete_domain.rb +0 -0
  29. data/{vmc-ng/lib → lib}/vmc/cli/domain/domains.rb +0 -0
  30. data/{vmc-ng/lib → lib}/vmc/cli/domain/remove_domain.rb +0 -0
  31. data/{vmc-ng/lib → lib}/vmc/cli/help.rb +0 -0
  32. data/{vmc-ng/lib → lib}/vmc/cli/interactive.rb +0 -0
  33. data/{vmc-ng/lib → lib}/vmc/cli/organization.rb +0 -0
  34. data/{vmc-ng/lib → lib}/vmc/cli/route/base.rb +0 -0
  35. data/{vmc-ng/lib → lib}/vmc/cli/route/create_route.rb +0 -0
  36. data/{vmc-ng/lib → lib}/vmc/cli/route/delete_route.rb +0 -0
  37. data/{vmc-ng/lib → lib}/vmc/cli/route/routes.rb +0 -0
  38. data/{vmc-ng/lib → lib}/vmc/cli/service.rb +0 -0
  39. data/{vmc-ng/lib → lib}/vmc/cli/space.rb +0 -0
  40. data/{vmc-ng/lib → lib}/vmc/cli/start.rb +0 -0
  41. data/{vmc-ng/lib → lib}/vmc/cli/user.rb +0 -0
  42. data/{vmc-ng/lib → lib}/vmc/constants.rb +0 -0
  43. data/{vmc-ng/lib → lib}/vmc/detect.rb +0 -0
  44. data/{vmc-ng/lib → lib}/vmc/errors.rb +0 -0
  45. data/{vmc-ng/lib → lib}/vmc/plugin.rb +0 -0
  46. data/{vmc-ng/lib → lib}/vmc/spacing.rb +0 -0
  47. data/{vmc-ng/lib → lib}/vmc/spec_helper.rb +0 -0
  48. data/lib/vmc/version.rb +3 -0
  49. data/{vmc-ng/spec → spec}/cli/app/push_spec.rb +0 -0
  50. data/{vmc-ng/spec → spec}/cli/app/rename_spec.rb +0 -0
  51. data/{vmc-ng/spec → spec}/cli/route/delete_route_spec.rb +0 -0
  52. data/{vmc-ng/spec → spec}/detect_spec.rb +0 -0
  53. data/{vmc-ng/spec → spec}/factories/app_factory.rb +0 -0
  54. data/{vmc-ng/spec → spec}/factories/client_factory.rb +0 -0
  55. data/{vmc-ng/spec → spec}/factories/domain_factory.rb +0 -0
  56. data/{vmc-ng/spec → spec}/factories/factory.rb +0 -0
  57. data/{vmc-ng/spec → spec}/factories/framework_factory.rb +0 -0
  58. data/{vmc-ng/spec → spec}/factories/route_factory.rb +0 -0
  59. data/{vmc-ng/spec → spec}/spec_helper.rb +0 -0
  60. data/{vmc-ng/spec → spec}/support/interact_helpers.rb +0 -0
  61. metadata +269 -486
  62. data/vmc-ng/bin/vmc +0 -11
  63. data/vmc-ng/lib/vmc/version.rb +0 -3
  64. data/vmc/LICENSE +0 -24
  65. data/vmc/README.md +0 -106
  66. data/vmc/Rakefile +0 -101
  67. data/vmc/bin/vmc +0 -6
  68. data/vmc/caldecott_helper/Gemfile +0 -10
  69. data/vmc/caldecott_helper/Gemfile.lock +0 -48
  70. data/vmc/caldecott_helper/server.rb +0 -43
  71. data/vmc/config/clients.yml +0 -17
  72. data/vmc/config/micro/offline.conf +0 -2
  73. data/vmc/config/micro/paths.yml +0 -22
  74. data/vmc/config/micro/refresh_ip.rb +0 -20
  75. data/vmc/lib/cli.rb +0 -47
  76. data/vmc/lib/cli/commands/admin.rb +0 -80
  77. data/vmc/lib/cli/commands/apps.rb +0 -1126
  78. data/vmc/lib/cli/commands/base.rb +0 -227
  79. data/vmc/lib/cli/commands/manifest.rb +0 -56
  80. data/vmc/lib/cli/commands/micro.rb +0 -115
  81. data/vmc/lib/cli/commands/misc.rb +0 -129
  82. data/vmc/lib/cli/commands/services.rb +0 -180
  83. data/vmc/lib/cli/commands/user.rb +0 -69
  84. data/vmc/lib/cli/config.rb +0 -173
  85. data/vmc/lib/cli/console_helper.rb +0 -170
  86. data/vmc/lib/cli/core_ext.rb +0 -122
  87. data/vmc/lib/cli/errors.rb +0 -19
  88. data/vmc/lib/cli/frameworks.rb +0 -265
  89. data/vmc/lib/cli/manifest_helper.rb +0 -302
  90. data/vmc/lib/cli/runner.rb +0 -531
  91. data/vmc/lib/cli/services_helper.rb +0 -84
  92. data/vmc/lib/cli/tunnel_helper.rb +0 -332
  93. data/vmc/lib/cli/usage.rb +0 -115
  94. data/vmc/lib/cli/version.rb +0 -7
  95. data/vmc/lib/cli/zip_util.rb +0 -77
  96. data/vmc/lib/vmc.rb +0 -3
  97. data/vmc/lib/vmc/client.rb +0 -471
  98. data/vmc/lib/vmc/const.rb +0 -22
  99. data/vmc/lib/vmc/micro.rb +0 -56
  100. data/vmc/lib/vmc/micro/switcher/base.rb +0 -97
  101. data/vmc/lib/vmc/micro/switcher/darwin.rb +0 -19
  102. data/vmc/lib/vmc/micro/switcher/dummy.rb +0 -15
  103. data/vmc/lib/vmc/micro/switcher/linux.rb +0 -16
  104. data/vmc/lib/vmc/micro/switcher/windows.rb +0 -31
  105. data/vmc/lib/vmc/micro/vmrun.rb +0 -168
@@ -1,180 +0,0 @@
1
- require "uuidtools"
2
-
3
- module VMC::Cli::Command
4
-
5
- class Services < Base
6
- include VMC::Cli::ServicesHelper
7
- include VMC::Cli::TunnelHelper
8
-
9
- def services
10
- ss = client.services_info
11
- ps = client.services
12
- ps.sort! {|a, b| a[:name] <=> b[:name] }
13
-
14
- if @options[:json]
15
- services = { :system => ss, :provisioned => ps }
16
- return display JSON.pretty_generate(services)
17
- end
18
- display_system_services(ss)
19
- display_provisioned_services(ps)
20
- end
21
-
22
- def create_service(service=nil, name=nil, appname=nil)
23
- unless no_prompt || service
24
- services = client.services_info
25
- err 'No services available to provision' if services.empty?
26
- service = ask(
27
- "Which service would you like to provision?",
28
- { :indexed => true,
29
- :choices =>
30
- services.values.collect { |type|
31
- type.keys.collect(&:to_s)
32
- }.flatten
33
- }
34
- )
35
- end
36
- name = @options[:name] unless name
37
- unless name
38
- name = random_service_name(service)
39
- picked_name = true
40
- end
41
- create_service_banner(service, name, picked_name)
42
- appname = @options[:bind] unless appname
43
- bind_service_banner(name, appname) if appname
44
- end
45
-
46
- def delete_service(service=nil)
47
- unless no_prompt || service
48
- user_services = client.services
49
- err 'No services available to delete' if user_services.empty?
50
- service = ask(
51
- "Which service would you like to delete?",
52
- { :indexed => true,
53
- :choices => user_services.collect { |s| s[:name] }
54
- }
55
- )
56
- end
57
- err "Service name required." unless service
58
- display "Deleting service [#{service}]: ", false
59
- client.delete_service(service)
60
- display 'OK'.green
61
- end
62
-
63
- def bind_service(service, appname)
64
- bind_service_banner(service, appname)
65
- end
66
-
67
- def unbind_service(service, appname)
68
- unbind_service_banner(service, appname)
69
- end
70
-
71
- def clone_services(src_app, dest_app)
72
- begin
73
- src = client.app_info(src_app)
74
- dest = client.app_info(dest_app)
75
- rescue
76
- end
77
-
78
- err "Application '#{src_app}' does not exist" unless src
79
- err "Application '#{dest_app}' does not exist" unless dest
80
-
81
- services = src[:services]
82
- err 'No services to clone' unless services && !services.empty?
83
- services.each { |service| bind_service_banner(service, dest_app, false) }
84
- check_app_for_restart(dest_app)
85
- end
86
-
87
- def tunnel(service=nil, client_name=nil)
88
- unless defined? Caldecott
89
- display "To use `vmc tunnel', you must first install Caldecott:"
90
- display ""
91
- display "\tgem install caldecott"
92
- display ""
93
- display "Note that you'll need a C compiler. If you're on OS X, Xcode"
94
- display "will provide one. If you're on Windows, try DevKit."
95
- display ""
96
- display "This manual step will be removed in the future."
97
- display ""
98
- err "Caldecott is not installed."
99
- end
100
-
101
- ps = client.services
102
- err "No services available to tunnel to" if ps.empty?
103
-
104
- unless service
105
- choices = ps.collect { |s| s[:name] }.sort
106
- service = ask(
107
- "Which service to tunnel to?",
108
- :choices => choices,
109
- :indexed => true
110
- )
111
- end
112
-
113
- info = ps.select { |s| s[:name] == service }.first
114
-
115
- err "Unknown service '#{service}'" unless info
116
-
117
- port = pick_tunnel_port(@options[:port] || 10000)
118
-
119
- raise VMC::Client::AuthError unless client.logged_in?
120
-
121
- if not tunnel_pushed?
122
- display "Deploying tunnel application '#{tunnel_appname}'."
123
- auth = UUIDTools::UUID.random_create.to_s
124
- push_caldecott(auth)
125
- bind_service_banner(service, tunnel_appname, false)
126
- start_caldecott
127
- else
128
- auth = tunnel_auth
129
- end
130
-
131
- if not tunnel_healthy?(auth)
132
- display "Redeploying tunnel application '#{tunnel_appname}'."
133
-
134
- # We don't expect caldecott not to be running, so take the
135
- # most aggressive restart method.. delete/re-push
136
- client.delete_app(tunnel_appname)
137
- invalidate_tunnel_app_info
138
-
139
- push_caldecott(auth)
140
- bind_service_banner(service, tunnel_appname, false)
141
- start_caldecott
142
- end
143
-
144
- if not tunnel_bound?(service)
145
- bind_service_banner(service, tunnel_appname)
146
- end
147
-
148
- conn_info = tunnel_connection_info info[:vendor], service, auth
149
- display_tunnel_connection_info(conn_info)
150
- display "Starting tunnel to #{service.bold} on port #{port.to_s.bold}."
151
- start_tunnel(port, conn_info, auth)
152
-
153
- clients = get_clients_for(info[:vendor])
154
-
155
- if clients.empty?
156
- client_name ||= "none"
157
- else
158
- client_name ||= ask(
159
- "Which client would you like to start?",
160
- :choices => ["none"] + clients.keys,
161
- :indexed => true
162
- )
163
- end
164
-
165
- if client_name == "none"
166
- wait_for_tunnel_end
167
- else
168
- wait_for_tunnel_start(port)
169
- unless start_local_prog(clients, client_name, conn_info, port)
170
- err "'#{client_name}' execution failed; is it in your $PATH?"
171
- end
172
- end
173
- end
174
-
175
- def get_clients_for(type)
176
- conf = VMC::Cli::Config.clients
177
- conf[type] || {}
178
- end
179
- end
180
- end
@@ -1,69 +0,0 @@
1
- require "cfoundry"
2
-
3
- module VMC::Cli::Command
4
-
5
- class User < Base
6
-
7
- def info
8
- info = client_info
9
- username = info[:user] || 'N/A'
10
- return display JSON.pretty_generate([username]) if @options[:json]
11
- display "\n[#{username}]"
12
- end
13
-
14
- def login(email=nil)
15
- email = @options[:email] unless email
16
- password = @options[:password]
17
- tries ||= 0
18
-
19
- unless no_prompt
20
- display "Attempting login to [#{target_url}]" if target_url
21
- email ||= ask("Email")
22
- password ||= ask("Password", :echo => "*")
23
- end
24
-
25
- err "Need a valid email" unless email
26
- err "Need a password" unless password
27
- login_and_save_token(email, password)
28
- say "Successfully logged into [#{target_url}]".green
29
- rescue CFoundry::Denied
30
- display "Problem with login, invalid account or password when attempting to login to '#{target_url}'".red
31
- retry if (tries += 1) < 3 && prompt_ok && !@options[:password]
32
- exit 1
33
- rescue => e
34
- display "Problem with login to '#{target_url}', #{e}, try again or register for an account.".red
35
- exit 1
36
- end
37
-
38
- def logout
39
- VMC::Cli::Config.remove_token_file
40
- say "Successfully logged out of [#{target_url}]".green
41
- end
42
-
43
- def change_password(password=nil)
44
- info = client_info
45
- email = info[:user]
46
- err "Need to be logged in to change password." unless email
47
- say "Changing password for '#{email}'\n"
48
- unless no_prompt
49
- password = ask "New Password", :echo => "*"
50
- password2 = ask "Verify Password", :echo => "*"
51
- err "Passwords did not match, try again" if password != password2
52
- end
53
- err "Password required" unless password
54
- client.change_password(password)
55
- say "\nSuccessfully changed password".green
56
- end
57
-
58
- private
59
-
60
- def login_and_save_token(email, password)
61
- cfoundry = CFoundry::Client.new(client.target)
62
- cfoundry.trace = @client.trace
63
- token = cfoundry.login(:username => email, :password => password)
64
- VMC::Cli::Config.store_token(token, @options[:token_file])
65
- end
66
-
67
- end
68
-
69
- end
@@ -1,173 +0,0 @@
1
- require "yaml"
2
- require 'fileutils'
3
-
4
- require 'rubygems'
5
- require 'json/pure'
6
-
7
- module VMC::Cli
8
- class Config
9
-
10
- DEFAULT_TARGET = 'api.vcap.me'
11
-
12
- TARGET_FILE = '~/.vmc_target'
13
- TOKEN_FILE = '~/.vmc_token'
14
- INSTANCES_FILE = '~/.vmc_instances'
15
- ALIASES_FILE = '~/.vmc_aliases'
16
- CLIENTS_FILE = '~/.vmc_clients'
17
- MICRO_FILE = '~/.vmc_micro'
18
-
19
- STOCK_CLIENTS = File.expand_path("../../../config/clients.yml", __FILE__)
20
-
21
- class << self
22
- attr_accessor :colorize
23
- attr_accessor :output
24
- attr_accessor :trace
25
- attr_accessor :nozip
26
-
27
- def target_url
28
- return @target_url if @target_url
29
- target_file = File.expand_path(TARGET_FILE)
30
- if File.exists? target_file
31
- @target_url = lock_and_read(target_file).strip
32
- else
33
- @target_url = DEFAULT_TARGET
34
- end
35
- @target_url = "http://#{@target_url}" unless /^https?/ =~ @target_url
36
- @target_url = @target_url.gsub(/\/+$/, '')
37
- @target_url
38
- end
39
-
40
- def base_of(url)
41
- url.sub(/^[^\.]+\./, "")
42
- end
43
-
44
- def suggest_url
45
- @suggest_url ||= base_of(target_url)
46
- end
47
-
48
- def store_target(target_host)
49
- target_file = File.expand_path(TARGET_FILE)
50
- lock_and_write(target_file, target_host)
51
- end
52
-
53
- def all_tokens(token_file_path=nil)
54
- token_file = File.expand_path(token_file_path || TOKEN_FILE)
55
- return nil unless File.exists? token_file
56
- contents = lock_and_read(token_file).strip
57
- JSON.parse(contents)
58
- end
59
-
60
- alias :targets :all_tokens
61
-
62
- def auth_token(token_file_path=nil)
63
- return @token if @token
64
- tokens = all_tokens(token_file_path)
65
- @token = tokens[target_url] if tokens
66
- end
67
-
68
- def remove_token_file
69
- FileUtils.rm_f(File.expand_path(TOKEN_FILE))
70
- end
71
-
72
- def store_token(token, token_file_path=nil)
73
- tokens = all_tokens(token_file_path) || {}
74
- tokens[target_url] = token
75
- token_file = File.expand_path(token_file_path || TOKEN_FILE)
76
- lock_and_write(token_file, tokens.to_json)
77
- end
78
-
79
- def instances
80
- instances_file = File.expand_path(INSTANCES_FILE)
81
- return nil unless File.exists? instances_file
82
- contents = lock_and_read(instances_file).strip
83
- JSON.parse(contents)
84
- end
85
-
86
- def store_instances(instances)
87
- instances_file = File.expand_path(INSTANCES_FILE)
88
- lock_and_write(instances_file, instances.to_json)
89
- end
90
-
91
- def aliases
92
- aliases_file = File.expand_path(ALIASES_FILE)
93
- # bacward compatible
94
- unless File.exists? aliases_file
95
- old_aliases_file = File.expand_path('~/.vmc-aliases')
96
- FileUtils.mv(old_aliases_file, aliases_file) if File.exists? old_aliases_file
97
- end
98
- aliases = YAML.load_file(aliases_file) rescue {}
99
- end
100
-
101
- def store_aliases(aliases)
102
- aliases_file = File.expand_path(ALIASES_FILE)
103
- File.open(aliases_file, 'wb') {|f| f.write(aliases.to_yaml)}
104
- end
105
-
106
- def micro
107
- micro_file = File.expand_path(MICRO_FILE)
108
- return {} unless File.exists? micro_file
109
- contents = lock_and_read(micro_file).strip
110
- JSON.parse(contents)
111
- end
112
-
113
- def store_micro(micro)
114
- micro_file = File.expand_path(MICRO_FILE)
115
- lock_and_write(micro_file, micro.to_json)
116
- end
117
-
118
- def deep_merge(a, b)
119
- merge = proc do |_, old, new|
120
- if new.is_a?(Hash) and old.is_a?(Hash)
121
- old.merge(new, &merge)
122
- else
123
- new
124
- end
125
- end
126
-
127
- a.merge(b, &merge)
128
- end
129
-
130
- def clients
131
- return @clients if @clients
132
-
133
- stock = YAML.load_file(STOCK_CLIENTS)
134
- clients = File.expand_path CLIENTS_FILE
135
- if File.exists? clients
136
- user = YAML.load_file(clients)
137
- @clients = deep_merge(stock, user)
138
- else
139
- @clients = stock
140
- end
141
- end
142
-
143
- def lock_and_read(file)
144
- File.open(file, File::RDONLY) {|f|
145
- if defined? JRUBY_VERSION
146
- f.flock(File::LOCK_SH)
147
- else
148
- f.flock(File::LOCK_EX)
149
- end
150
- contents = f.read
151
- f.flock(File::LOCK_UN)
152
- contents
153
- }
154
- end
155
-
156
- def lock_and_write(file, contents)
157
- File.open(file, File::RDWR | File::CREAT, 0600) {|f|
158
- f.flock(File::LOCK_EX)
159
- f.rewind
160
- f.puts contents
161
- f.flush
162
- f.truncate(f.pos)
163
- f.flock(File::LOCK_UN)
164
- }
165
- end
166
- end
167
-
168
- def initialize(work_dir = Dir.pwd)
169
- @work_dir = work_dir
170
- end
171
-
172
- end
173
- end
@@ -1,170 +0,0 @@
1
- require 'net/telnet'
2
- require 'readline'
3
-
4
- module VMC::Cli
5
- module ConsoleHelper
6
-
7
- def console_connection_info(appname)
8
- app = client.app_info(appname)
9
- fw = VMC::Cli::Framework.lookup_by_framework(app[:staging][:model])
10
- if !fw.console
11
- err "'#{appname}' is a #{fw.name} application. " +
12
- "Console access is not supported for #{fw.name} applications."
13
- end
14
- instances_info_envelope = client.app_instances(appname)
15
- instances_info_envelope = {} if instances_info_envelope.is_a?(Array)
16
-
17
- instances_info = instances_info_envelope[:instances] || []
18
- err "No running instances for [#{appname}]" if instances_info.empty?
19
-
20
- entry = instances_info[0]
21
- if !entry[:console_port]
22
- begin
23
- client.app_files(appname, '/app/cf-rails-console')
24
- err "Console port not provided for [#{appname}]. Try restarting the app."
25
- rescue VMC::Client::TargetError, VMC::Client::NotFound
26
- err "Console access not supported for [#{appname}]. " +
27
- "Please redeploy your app to enable support."
28
- end
29
- end
30
- conn_info = {'hostname' => entry[:console_ip], 'port' => entry[:console_port]}
31
- end
32
-
33
- def start_local_console(port, appname)
34
- auth_info = console_credentials(appname)
35
- banner = "Connecting to '#{appname}' console: "
36
- display banner, false
37
- t = Thread.new do
38
- count = 0
39
- while count < 90 do
40
- display '.', false
41
- sleep 1
42
- count += 1
43
- end
44
- end
45
- prompt = console_login(auth_info, port)
46
- Thread.kill(t)
47
- clear(80)
48
- display "#{banner}#{'OK'.green}"
49
- display "\n"
50
- initialize_readline
51
- run_console prompt
52
- end
53
-
54
- def console_login(auth_info, port)
55
- if !auth_info["username"] || !auth_info["password"]
56
- err "Unable to verify console credentials."
57
- end
58
- @telnet_client = telnet_client(port)
59
- prompt = nil
60
- err_msg = "Login attempt timed out."
61
- 3.times do
62
- begin
63
- results = @telnet_client.login("Name"=>auth_info["username"],
64
- "Password"=>auth_info["password"])
65
- lines = results.sub("Login: Password: ", "").split("\n")
66
- last_line = lines.pop
67
- if last_line =~ /[$%#>] \z/n
68
- prompt = last_line
69
- elsif last_line =~ /Login failed/
70
- err_msg = last_line
71
- end
72
- break
73
- rescue TimeoutError
74
- sleep 1
75
- rescue EOFError
76
- #This may happen if we login right after app starts
77
- close_console
78
- sleep 5
79
- @telnet_client = telnet_client(port)
80
- end
81
- end
82
- unless prompt
83
- close_console
84
- err err_msg
85
- end
86
- prompt
87
- end
88
-
89
- def send_console_command(cmd)
90
- results = @telnet_client.cmd(cmd)
91
- results.split("\n")
92
- end
93
-
94
- def console_credentials(appname)
95
- content = client.app_files(appname, '/app/cf-rails-console/.consoleaccess', '0')
96
- YAML.load(content)
97
- end
98
-
99
- def close_console
100
- @telnet_client.close
101
- end
102
-
103
- def console_tab_completion_data(cmd)
104
- begin
105
- results = @telnet_client.cmd("String"=> cmd + "\t", "Match"=>/\S*\n$/, "Timeout"=>10)
106
- results.chomp.split(",")
107
- rescue TimeoutError
108
- [] #Just return empty results if timeout occurred on tab completion
109
- end
110
- end
111
-
112
- private
113
- def telnet_client(port)
114
- Net::Telnet.new({"Port"=>port, "Prompt"=>/[$%#>] \z|Login failed/n, "Timeout"=>30, "FailEOF"=>true})
115
- end
116
-
117
- def readline_with_history(prompt)
118
- line = Readline::readline(prompt)
119
- return nil if line == nil || line == 'quit' || line == 'exit'
120
- Readline::HISTORY.push(line) if not line =~ /^\s*$/ and Readline::HISTORY.to_a[-1] != line
121
- line
122
- end
123
-
124
- def run_console(prompt)
125
- prev = trap("INT") { |x| exit_console; prev.call(x); exit }
126
- prev = trap("TERM") { |x| exit_console; prev.call(x); exit }
127
- loop do
128
- cmd = readline_with_history(prompt)
129
- if(cmd == nil)
130
- exit_console
131
- break
132
- end
133
- prompt = send_console_command_display_results(cmd, prompt)
134
- end
135
- end
136
-
137
- def exit_console
138
- #TimeoutError expected, as exit doesn't return anything
139
- @telnet_client.cmd("String"=>"exit","Timeout"=>1) rescue TimeoutError
140
- close_console
141
- end
142
-
143
- def send_console_command_display_results(cmd, prompt)
144
- begin
145
- lines = send_console_command cmd
146
- #Assumes the last line is a prompt
147
- prompt = lines.pop
148
- lines.each {|line| display line if line != cmd}
149
- rescue TimeoutError
150
- display "Timed out sending command to server.".red
151
- rescue EOFError
152
- err "The console connection has been terminated. Perhaps the app was stopped or deleted?"
153
- end
154
- prompt
155
- end
156
-
157
- def initialize_readline
158
- if Readline.respond_to?("basic_word_break_characters=")
159
- Readline.basic_word_break_characters= " \t\n`><=;|&{("
160
- end
161
- Readline.completion_append_character = nil
162
- #Assumes that sending a String ending with tab will return a non-empty
163
- #String of comma-separated completion options, terminated by a new line
164
- #For example, "app.\t" might result in "to_s,nil?,etc\n"
165
- Readline.completion_proc = proc {|s|
166
- console_tab_completion_data s
167
- }
168
- end
169
- end
170
- end