vmc 0.4.0.beta.97 → 0.4.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 (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