lds-cf-plugin 0.2.3 → 0.3.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.
@@ -1,5 +1,5 @@
1
1
  require "cf/cli"
2
- require "yajl"
2
+ require "json"
3
3
 
4
4
  module LdsCfPlugin
5
5
  class CustomService < CF::CLI
@@ -8,7 +8,7 @@ module LdsCfPlugin
8
8
  end
9
9
 
10
10
  desc "Create a custom service"
11
- group :lds
11
+ group :lds, :services
12
12
  input :name, :desc => "Name for your service", :argument => :optional
13
13
  input :credentials, :desc => "The service credentials JSON string to be passed to the application", :argument => :optional
14
14
  input :plan, :desc => "Service plan",
@@ -49,7 +49,7 @@ module LdsCfPlugin
49
49
  credentials = ask("Service credentials JSON string")
50
50
  end
51
51
 
52
- creds = Yajl::Parser.new.parse(credentials)
52
+ creds = JSON.parse(credentials)
53
53
 
54
54
  # Register custom service with gateway
55
55
 
@@ -59,7 +59,7 @@ module LdsCfPlugin
59
59
  :credentials => creds
60
60
  }
61
61
  options = {
62
- :payload => Yajl::Encoder.encode(payload)
62
+ :payload => JSON.generate(payload)
63
63
  }
64
64
  request, response = rest_client.request("POST", "/register", options)
65
65
  if response[:status].to_i != 200
@@ -1,5 +1,5 @@
1
1
  require "cf/cli"
2
- require "yajl"
2
+ require "json"
3
3
 
4
4
  module LdsCfPlugin
5
5
  class CustomService < CF::CLI
@@ -8,7 +8,7 @@ module LdsCfPlugin
8
8
  end
9
9
 
10
10
  desc "Create an Oracle service"
11
- group :lds
11
+ group :lds, :services
12
12
  input :name, :desc => "Name for your service", :argument => :optional
13
13
  input :service, :desc => "The Oracle database to connect to", :argument => :optional
14
14
  input :schema, :desc => "The schema (user) to use", :argument => :optional
@@ -71,11 +71,11 @@ module LdsCfPlugin
71
71
  :password => password
72
72
  }
73
73
  options = {
74
- :payload => Yajl::Encoder.encode(payload)
74
+ :payload => JSON.generate(payload)
75
75
  }
76
76
  request, response = rest_client.request("POST", "/register", options)
77
77
  if response[:status].to_i != 200
78
- fail "Error registering Oracle service with gateway. See details below:\n#{response[:body]}"
78
+ fail "Error registering Oracle service with gateway:\n#{response[:body]}"
79
79
  end
80
80
 
81
81
 
@@ -1,9 +1,11 @@
1
1
  require "mothership/help"
2
2
 
3
3
  Mothership::Help.groups(
4
- [:lds, "LDS Specific"]
4
+ [:lds, "LDS Specific",
5
+ [:services, "Services"],
6
+ [:diagnostics, "Diagnostics"]]
5
7
  )
6
8
 
7
9
  require "lds-cf-plugin/custom_service"
8
10
  require "lds-cf-plugin/oracle_service"
9
-
11
+ require "lds-cf-plugin/tunnel"
@@ -0,0 +1,102 @@
1
+ require 'eventmachine'
2
+ require 'interact/pretty'
3
+
4
+ module TunnelClient
5
+
6
+ PROTOCOL_VERSION = '1'.freeze
7
+
8
+ FRAME_HEADER_LENGTH = 5
9
+
10
+ extend Interact::Pretty
11
+
12
+ def self.tunnel(token, tunnel_server_host, tunnel_server_port, app, instance_id, port = 'debug', local_host = '127.0.0.1', local_port = 1847, use_tls = true)
13
+ EventMachine::start_server(local_host, local_port, TunnelListener, token, tunnel_server_host, tunnel_server_port, app.guid, instance_id, port, use_tls)
14
+ end
15
+
16
+ class TunnelListener < EventMachine::Connection
17
+
18
+ attr_reader :token
19
+ attr_reader :app_guid
20
+ attr_reader :instance_id
21
+ attr_reader :port
22
+ attr_reader :use_tls
23
+
24
+ def initialize(token, tunnel_server_host, tunnel_server_port, app_guid, instance_id, port, use_tls)
25
+ @token, @app_guid, @instance_id, @port, @use_tls = token, app_guid, instance_id, port, use_tls
26
+
27
+ @tunnel_server_host = tunnel_server_host
28
+ @tunnel_server_port = tunnel_server_port
29
+ end
30
+
31
+ def post_init
32
+ puts 'Opening new connection to server...'
33
+ pause
34
+ @connection = EventMachine.connect(@tunnel_server_host, @tunnel_server_port, TunnelConnection, self)
35
+ end
36
+
37
+ def unbind
38
+ puts "Connection closed"
39
+ @connection.close_connection_after_writing
40
+ end
41
+
42
+ end
43
+
44
+ class TunnelConnection < EventMachine::Connection
45
+
46
+ def initialize(listener)
47
+ @listener = listener
48
+ end
49
+
50
+ def post_init
51
+ puts "Connection opened"
52
+ if @listener.use_tls
53
+ start_tls
54
+ else
55
+ send_initialization
56
+ end
57
+ end
58
+
59
+ def ssl_handshake_completed
60
+ send_initialization
61
+ end
62
+
63
+ def receive_data(data)
64
+ (@buf ||= '') << data
65
+
66
+ while @buf.bytesize >= FRAME_HEADER_LENGTH
67
+ frame_type, frame_length = @buf.unpack("A1N")
68
+ if @buf.bytesize >= FRAME_HEADER_LENGTH + frame_length
69
+ @buf.slice!(0,FRAME_HEADER_LENGTH)
70
+ frame_body = @buf.slice!(0,frame_length)
71
+ case frame_type
72
+ when 'E', 'e'
73
+ # Error
74
+ close_connection
75
+ raise frame_body
76
+ when 'R', 'r'
77
+ @listener.resume
78
+ proxy_incoming_to @listener
79
+ @listener.proxy_incoming_to self
80
+ else
81
+ close_connection
82
+ raise "Received invalid frame type '#{frame_type}' from Tunnel Server"
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ def unbind
89
+ @listener.close_connection_after_writing
90
+ end
91
+
92
+ private
93
+
94
+ def send_initialization
95
+ frame_body = "#{PROTOCOL_VERSION} #{@listener.token} #{@listener.app_guid} #{@listener.instance_id} #{@listener.port}"
96
+ frame = ['I', frame_body.bytesize, frame_body]
97
+ send_data frame.pack("A1NA*")
98
+ end
99
+
100
+ end
101
+
102
+ end
@@ -0,0 +1,192 @@
1
+ require "cf/cli"
2
+ require "cf/constants"
3
+ require 'eventmachine'
4
+ require "lds-cf-plugin/tunnel/tunnelclient"
5
+ require "open-uri"
6
+ require "uri"
7
+
8
+ module LdsCfPlugin
9
+
10
+ JMXMP_JAR_NAME = "jmxremote_optional-repackaged-4.0.jar".freeze
11
+ JMXMP_JAR_FILE = File.expand_path("#{CF::CONFIG_DIR}/jmxremote_optional-repackaged-4.0.jar").freeze
12
+ JMXMP_JAR_URL = "http://search.maven.org/remotecontent?filepath=org/glassfish/main/external/jmxremote_optional-repackaged/4.0/#{JMXMP_JAR_NAME}".freeze
13
+
14
+ class Tunnel < CF::CLI
15
+ def precondition
16
+ check_target
17
+ end
18
+
19
+ desc "Open tunnel to application's debug port"
20
+ group :lds, :diagnostics
21
+ input :app, :desc => "Application to debug", :argument => :optional,
22
+ :from_given => by_name(:app)
23
+ input :instance, :desc => "Application instance", :argument => :optional
24
+ input :host, :desc => "The local host to bind to for tunneling connections",
25
+ :default => "127.0.0.1", :aliases => "--host"
26
+ input :port, :desc => "The local port to listen on for tunneling connections",
27
+ :default => 1847, :aliases => "--port"
28
+ input :tunnel_server, :desc => "The server to connect to for tunneling to the application",
29
+ :aliases => "--server"
30
+ input :tunnel_server_port, :desc => "The port to connect to on the tunnel server",
31
+ :aliases => "--server-port", :default => 2014
32
+ input :use_tls, :desc => "Indicates if TLS should be used", :default => true
33
+ def tunnel_debug
34
+ app = input[:app]
35
+ instances = get_instances(app)
36
+
37
+ filter_debug_instances(app, instances)
38
+
39
+ unless instances.size > 0
40
+ if ask("Restart application #{c(app.name, :name)} in debug mode?", :default => true)
41
+ invoke :restart, :app => app, :debug_mode => ""
42
+
43
+ instances = get_instances(app)
44
+ filter_debug_instances(app, instances)
45
+ else
46
+ fail "Unable to debug #{c(app.name, :name)} because it is not running in debug mode."
47
+ end
48
+ end
49
+
50
+ fail "Debugger information for #{c(app.name, :name)} still not available." unless instances.size > 0
51
+
52
+ tunnel(app, instances, "debug")
53
+ end
54
+
55
+ def filter_debug_instances(app, instances)
56
+ instances.keep_if do |instance|
57
+ debugger = instance.debugger
58
+ puts "#{c('Debugger information for instance', :error)} ##{c(instance.id, :number)} #{c('of', :error)} #{c(app.name, :name)} #{c('not available', :error)}" unless debugger
59
+ debugger
60
+ end
61
+ end
62
+
63
+ desc "Open tunnel to application's console port"
64
+ group :lds, :diagnostics
65
+ input :app, :desc => "Application to connect the console to", :argument => :optional,
66
+ :from_given => by_name(:app)
67
+ input :instance, :desc => "Application instance", :argument => :optional
68
+ input :host, :desc => "The local host to bind to for tunneling connections",
69
+ :default => "127.0.0.1", :aliases => "--host"
70
+ input :port, :desc => "The local port to listen on for tunneling connections",
71
+ :default => 1830, :aliases => "--port"
72
+ input :tunnel_server, :desc => "The server to connect to for tunneling to the application",
73
+ :aliases => "--server"
74
+ input :tunnel_server_port, :desc => "The port to connect to on the tunnel server",
75
+ :aliases => "--server-port", :default => 2014
76
+ input :use_tls, :desc => "Indicates if TLS should be used", :default => true
77
+ def tunnel_console(&post_tunnel)
78
+ app = input[:app]
79
+ instances = get_instances(app)
80
+
81
+ instances.keep_if do |instance|
82
+ console = instance.console
83
+ puts "#{c('Console information for instance', :error)} ##{c(instance.id, :number)} #{c('of', :error)} #{c(app.name, :name)} #{c(' not available', :error)}" unless console
84
+ console
85
+ end
86
+
87
+ fail "Console information for #{c(app.name, :name)} not available." unless instances.size > 0
88
+
89
+ tunnel(app, instances, "console", &post_tunnel)
90
+ end
91
+
92
+ desc "Launch VisualVM and connect to each instance of application"
93
+ group :lds, :diagnostics
94
+ input :app, :desc => "Application VisualVM will connect to", :argument => :optional,
95
+ :from_given => by_name(:app)
96
+ input :instance, :desc => "Application instance", :argument => :optional
97
+ input :host, :desc => "The local host to bind to for tunneling connections",
98
+ :default => "127.0.0.1", :aliases => "--host"
99
+ input :port, :desc => "The local port to listen on for tunneling connections",
100
+ :default => 1830, :aliases => "--port"
101
+ input :tunnel_server, :desc => "The server to connect to for tunneling to the application",
102
+ :aliases => "--server"
103
+ input :tunnel_server_port, :desc => "The port to connect to on the tunnel server",
104
+ :aliases => "--server-port", :default => 2014
105
+ input :use_tls, :desc => "Indicates if TLS should be used", :default => true
106
+ input :jvisualvm, :desc => "The location of the jvisualvm executable to be used", :aliases => "--jvisualvm"
107
+ def visualvm
108
+ if !File::exist?(JMXMP_JAR_FILE)
109
+ with_progress("Downloading JMXMP extension") do
110
+ File.open(JMXMP_JAR_FILE, "wb") do |saved_file|
111
+ open(JMXMP_JAR_URL, 'rb') do |read_file|
112
+ saved_file.write(read_file.read)
113
+ end
114
+ end
115
+ end
116
+ end
117
+ tunnel_console do |instances|
118
+ visualvm = input[:jvisualvm] ? input[:jvisualvm] : "jvisualvm"
119
+ EventMachine::defer do
120
+ if system("#{visualvm} -cp:a #{JMXMP_JAR_FILE}") == nil
121
+ fail("Unable to run '#{visualvm}'. Is it in your PATH?")
122
+ end
123
+ end
124
+
125
+ EventMachine::defer do
126
+ # Give jvisualvm time to start up
127
+ sleep(5)
128
+ host = input[:host]
129
+ port = input[:port]
130
+
131
+ instances.each do |instance|
132
+ jmxurl = "service:jmx:jmxmp://#{host}:#{port}"
133
+ puts "Adding instance #{c('#' + instance.id, :instance)} to VisualVM (#{c(jmxurl, :instance)})"
134
+ system("#{visualvm} --openjmx #{jmxurl}")
135
+ port = port + 1
136
+ end
137
+ end
138
+ end
139
+ end
140
+
141
+ def tunnel(app, instances, mode, &post_tunnel)
142
+ server = input[:tunnel_server] ? input[:tunnel_server] : URI(client.target).host
143
+ server_port = input[:tunnel_server_port]
144
+
145
+ host = input[:host]
146
+ port = input[:port]
147
+
148
+ line
149
+
150
+ EventMachine.error_handler do |e|
151
+ EventMachine.stop_event_loop
152
+
153
+ log_error(e)
154
+ end
155
+
156
+ EventMachine.run do
157
+ instances.each do |instance|
158
+ TunnelClient::tunnel(client.token.auth_header, server, server_port, app, instance.id, mode, host, port, input[:use_tls])
159
+ puts "Listening on #{c(host + ':' + port.to_s, :number)} for #{c(mode, :warning)} connections to forward to #{c(app.name, :name)} instance #{c('#' + instance.id, :instance)}."
160
+ port = port + 1
161
+ end
162
+ yield instances if post_tunnel
163
+ end
164
+ end
165
+
166
+ private
167
+
168
+ def ask_app
169
+ ask "Which application?", :choices => client.apps,
170
+ :display => proc(&:name)
171
+ end
172
+
173
+ def get_instances(app)
174
+ instances = with_progress ("Getting instances for #{c(app.name, :name)}") do
175
+ app.instances
176
+ end
177
+
178
+ fail "No instances of #{c(app.name, :name)} are running." if instances.length == 0
179
+
180
+ instances.sort! { |a, b| a.id.to_i <=> b.id.to_i }
181
+
182
+ if input[:instance]
183
+ instance = input[:instance].to_i
184
+ instances = [ instances[instance] ]
185
+ end
186
+
187
+ instances
188
+ end
189
+
190
+ end
191
+
192
+ end
@@ -1,3 +1,3 @@
1
1
  module LdsCfPlugin
2
- VERSION = "0.2.3".freeze
2
+ VERSION = "0.3.0".freeze
3
3
  end
metadata CHANGED
@@ -1,69 +1,100 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: lds-cf-plugin
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
4
5
  prerelease:
5
- version: 0.2.3
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Mike Heath
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
-
13
- date: 2013-06-27 00:00:00 Z
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
12
+ date: 2013-07-17 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
16
15
  name: cfoundry
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.5.1
22
+ type: :runtime
17
23
  prerelease: false
18
- requirement: &id001 !ruby/object:Gem::Requirement
24
+ version_requirements: !ruby/object:Gem::Requirement
19
25
  none: false
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
23
29
  version: 1.5.1
30
+ - !ruby/object:Gem::Dependency
31
+ name: eventmachine
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '1.0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '1.0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: json_pure
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '1.6'
24
54
  type: :runtime
25
- version_requirements: *id001
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.6'
26
62
  description:
27
- email:
63
+ email:
28
64
  - heathma@ldschurch.org
29
65
  executables: []
30
-
31
66
  extensions: []
32
-
33
67
  extra_rdoc_files: []
34
-
35
- files:
68
+ files:
36
69
  - Rakefile
37
70
  - lib/lds-cf-plugin/custom_service.rb
38
71
  - lib/lds-cf-plugin/oracle_service.rb
72
+ - lib/lds-cf-plugin/tunnel.rb
39
73
  - lib/lds-cf-plugin/version.rb
40
74
  - lib/lds-cf-plugin/plugin.rb
41
- homepage: http://cloudfoundry.com/
75
+ - lib/lds-cf-plugin/tunnel/tunnelclient.rb
76
+ homepage: http://ui.app.lds.org/
42
77
  licenses: []
43
-
44
78
  post_install_message:
45
79
  rdoc_options: []
46
-
47
- require_paths:
80
+ require_paths:
48
81
  - lib
49
- required_ruby_version: !ruby/object:Gem::Requirement
82
+ required_ruby_version: !ruby/object:Gem::Requirement
50
83
  none: false
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: "0"
55
- required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
89
  none: false
57
- requirements:
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- version: "0"
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
61
94
  requirements: []
62
-
63
95
  rubyforge_project:
64
- rubygems_version: 1.8.24
96
+ rubygems_version: 1.8.23
65
97
  signing_key:
66
98
  specification_version: 3
67
99
  summary: Cloud Foundry commands for LDS PaaS.
68
100
  test_files: []
69
-