console-vmc-plugin 0.0.1
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/Rakefile +47 -0
- data/lib/console-vmc-plugin/console.rb +171 -0
- data/lib/console-vmc-plugin/plugin.rb +33 -0
- data/lib/console-vmc-plugin/version.rb +3 -0
- metadata +84 -0
data/Rakefile
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require "rake"
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
4
|
+
require "console-vmc-plugin/version"
|
5
|
+
|
6
|
+
task :default => :spec
|
7
|
+
|
8
|
+
desc "Run specs"
|
9
|
+
task :spec => ["bundler:install", "test:spec"]
|
10
|
+
|
11
|
+
desc "Run integration tests"
|
12
|
+
task :test => ["bundler:install", "test:integration"]
|
13
|
+
|
14
|
+
task :build do
|
15
|
+
sh "gem build console-vmc-plugin.gemspec"
|
16
|
+
end
|
17
|
+
|
18
|
+
task :install => :build do
|
19
|
+
sh "gem install --local console-vmc-plugin-#{VMCConsole::VERSION}.gem"
|
20
|
+
end
|
21
|
+
|
22
|
+
task :uninstall do
|
23
|
+
sh "gem uninstall console-vmc-plugin"
|
24
|
+
end
|
25
|
+
|
26
|
+
task :reinstall => [:uninstall, :install]
|
27
|
+
|
28
|
+
task :release => :build do
|
29
|
+
sh "gem push console-vmc-plugin-#{VMCConsole::VERSION}.gem"
|
30
|
+
end
|
31
|
+
|
32
|
+
namespace "bundler" do
|
33
|
+
desc "Install gems"
|
34
|
+
task "install" do
|
35
|
+
sh("bundle install")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
namespace "test" do
|
40
|
+
task "spec" do |t|
|
41
|
+
# nothing
|
42
|
+
end
|
43
|
+
|
44
|
+
task "integration" do |t|
|
45
|
+
sh("cd spec && bundle exec rake spec")
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
require "net/telnet"
|
2
|
+
require "readline"
|
3
|
+
|
4
|
+
require "tunnel-vmc-plugin/tunnel"
|
5
|
+
|
6
|
+
|
7
|
+
class CFConsole < CFTunnel
|
8
|
+
def initialize(client, app, port = 10000)
|
9
|
+
@client = client
|
10
|
+
@app = app
|
11
|
+
@port = port
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_connection_info(auth)
|
15
|
+
unless console = @app.instances[0].console
|
16
|
+
raise "App does not have console access; try restarting it."
|
17
|
+
end
|
18
|
+
|
19
|
+
{ "hostname" => console[:ip],
|
20
|
+
"port" => console[:port]
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_credentials
|
25
|
+
YAML.load(@app.file("app", "cf-rails-console", ".consoleaccess"))
|
26
|
+
end
|
27
|
+
|
28
|
+
def start_console
|
29
|
+
prompt = login
|
30
|
+
|
31
|
+
init_readline
|
32
|
+
|
33
|
+
run_console prompt
|
34
|
+
end
|
35
|
+
|
36
|
+
def login(auth = get_credentials)
|
37
|
+
if !auth["username"] || !auth["password"]
|
38
|
+
raise "Unable to verify console credentials."
|
39
|
+
end
|
40
|
+
|
41
|
+
@telnet = telnet_client
|
42
|
+
|
43
|
+
prompt = nil
|
44
|
+
err_msg = "Login attempt timed out."
|
45
|
+
|
46
|
+
5.times do
|
47
|
+
begin
|
48
|
+
results = @telnet.login(
|
49
|
+
"Name" => auth["username"],
|
50
|
+
"Password" => auth["password"])
|
51
|
+
|
52
|
+
lines = results.sub("Login: Password: ", "").split("\n")
|
53
|
+
|
54
|
+
last_line = lines.pop
|
55
|
+
|
56
|
+
if last_line =~ /[$%#>] \z/n
|
57
|
+
prompt = last_line
|
58
|
+
elsif last_line =~ /Login failed/
|
59
|
+
err_msg = last_line
|
60
|
+
end
|
61
|
+
|
62
|
+
break
|
63
|
+
|
64
|
+
rescue TimeoutError
|
65
|
+
sleep 1
|
66
|
+
|
67
|
+
rescue EOFError
|
68
|
+
# This may happen if we login right after app starts
|
69
|
+
close_console
|
70
|
+
sleep 5
|
71
|
+
@telnet = telnet_client
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
unless prompt
|
76
|
+
close_console
|
77
|
+
raise err_msg
|
78
|
+
end
|
79
|
+
|
80
|
+
prompt
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def init_readline
|
86
|
+
if Readline.respond_to?("basic_word_break_characters=")
|
87
|
+
Readline.basic_word_break_characters= " \t\n`><=;|&{("
|
88
|
+
end
|
89
|
+
|
90
|
+
Readline.completion_append_character = nil
|
91
|
+
|
92
|
+
# Assumes that sending a String ending with tab will return a non-empty
|
93
|
+
# String of comma-separated completion options, terminated by a new line
|
94
|
+
# For example, "app.\t" might result in "to_s,nil?,etc\n"
|
95
|
+
Readline.completion_proc = proc do |s|
|
96
|
+
console_tab_completion_data(s)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def run_console(prompt)
|
101
|
+
prev = trap("INT") { |x| exit_console; prev.call(x); exit }
|
102
|
+
prev = trap("TERM") { |x| exit_console; prev.call(x); exit }
|
103
|
+
|
104
|
+
loop do
|
105
|
+
cmd = readline_with_history(prompt)
|
106
|
+
|
107
|
+
if cmd == nil
|
108
|
+
exit_console
|
109
|
+
break
|
110
|
+
end
|
111
|
+
|
112
|
+
prompt = send_console_command_display_results(cmd, prompt)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def readline_with_history(prompt)
|
117
|
+
line = Readline::readline(prompt)
|
118
|
+
|
119
|
+
return if line == nil || line == 'quit' || line == 'exit'
|
120
|
+
|
121
|
+
if line !~ /^\s*$/ && Readline::HISTORY.to_a[-1] != line
|
122
|
+
Readline::HISTORY.push(line)
|
123
|
+
end
|
124
|
+
|
125
|
+
line
|
126
|
+
end
|
127
|
+
|
128
|
+
def send_console_command_display_results(cmd, prompt)
|
129
|
+
begin
|
130
|
+
lines = send_console_command cmd
|
131
|
+
|
132
|
+
# Assumes the last line is a prompt
|
133
|
+
prompt = lines.pop
|
134
|
+
|
135
|
+
lines.each do |line|
|
136
|
+
puts line if line != cmd
|
137
|
+
end
|
138
|
+
|
139
|
+
rescue TimeoutError
|
140
|
+
puts "Timed out sending command to server."
|
141
|
+
|
142
|
+
rescue EOFError
|
143
|
+
raise "The console connection has been terminated. Perhaps the app was stopped or deleted?"
|
144
|
+
end
|
145
|
+
|
146
|
+
prompt
|
147
|
+
end
|
148
|
+
|
149
|
+
def send_console_command(cmd)
|
150
|
+
results = @telnet.cmd(cmd)
|
151
|
+
results.split("\n")
|
152
|
+
end
|
153
|
+
|
154
|
+
def exit_console
|
155
|
+
# TimeoutError expected, as exit doesn't return anything
|
156
|
+
@telnet.cmd("String" => "exit", "Timeout" => 1) rescue TimeoutError
|
157
|
+
close_console
|
158
|
+
end
|
159
|
+
|
160
|
+
def close_console
|
161
|
+
@telnet.close
|
162
|
+
end
|
163
|
+
|
164
|
+
def telnet_client
|
165
|
+
Net::Telnet.new(
|
166
|
+
"Port" => @port,
|
167
|
+
"Prompt" => /[$%#>] \z|Login failed/n,
|
168
|
+
"Timeout" => 30,
|
169
|
+
"FailEOF" => true)
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "vmc/plugin"
|
2
|
+
require "console-vmc-plugin/console"
|
3
|
+
|
4
|
+
module VMCConsole
|
5
|
+
class Console < VMC::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 = CFConsole.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
|
+
filter(:start, :start_app) do |app|
|
26
|
+
if !v2? && app.framework.name == "rails3"
|
27
|
+
app.console = true
|
28
|
+
end
|
29
|
+
|
30
|
+
app
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: console-vmc-plugin
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Alex Suraci
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-09-17 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: tunnel-vmc-plugin
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ~>
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 31
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
- 1
|
32
|
+
- 2
|
33
|
+
version: 0.1.2
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
description:
|
37
|
+
email:
|
38
|
+
- asuraci@vmware.com
|
39
|
+
executables: []
|
40
|
+
|
41
|
+
extensions: []
|
42
|
+
|
43
|
+
extra_rdoc_files: []
|
44
|
+
|
45
|
+
files:
|
46
|
+
- Rakefile
|
47
|
+
- lib/console-vmc-plugin/console.rb
|
48
|
+
- lib/console-vmc-plugin/plugin.rb
|
49
|
+
- lib/console-vmc-plugin/version.rb
|
50
|
+
homepage: http://cloudfoundry.com/
|
51
|
+
licenses: []
|
52
|
+
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options: []
|
55
|
+
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
hash: 3
|
64
|
+
segments:
|
65
|
+
- 0
|
66
|
+
version: "0"
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
hash: 3
|
73
|
+
segments:
|
74
|
+
- 0
|
75
|
+
version: "0"
|
76
|
+
requirements: []
|
77
|
+
|
78
|
+
rubyforge_project: console-vmc-plugin
|
79
|
+
rubygems_version: 1.8.24
|
80
|
+
signing_key:
|
81
|
+
specification_version: 3
|
82
|
+
summary: Port of rails-console to vmc-ng.
|
83
|
+
test_files: []
|
84
|
+
|