console-vmc-plugin 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,3 @@
1
+ module VMCConsole
2
+ VERSION = "0.0.1"
3
+ 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
+