tail-cf-plugin 0.0.20.pre → 0.0.21.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,46 @@
1
+ module TailCfPlugin
2
+ class LogTarget
3
+ def initialize(target_organization, target_space, ids)
4
+ raise ArgumentError, "Requires 3 ids" unless ids.size == 3
5
+ @target_organization = target_organization
6
+ @target_space = target_space
7
+
8
+ @org_id = ids[0]
9
+ @space_id = ids[1]
10
+ @app_id = ids[2]
11
+ end
12
+
13
+ def ambiguous?
14
+ @target_organization && @target_space
15
+ end
16
+
17
+ def valid?
18
+ !!target
19
+ end
20
+
21
+ def query_params
22
+ case target
23
+ when :org
24
+ {org: @org_id}
25
+ when :space
26
+ {org: @org_id, space: @space_id}
27
+ when :app
28
+ {org: @org_id, space: @space_id, app: @app_id}
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def target
35
+ return nil if ambiguous?
36
+ case
37
+ when @target_organization
38
+ :org
39
+ when @target_space
40
+ :space
41
+ when @app_id
42
+ :app
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,16 +1,18 @@
1
1
  require 'log_message/log_message.pb'
2
2
  require 'faye/websocket'
3
3
  require 'eventmachine'
4
+ require 'uri'
4
5
 
5
6
  module TailCfPlugin
6
7
  class LoggregatorClient
7
- def initialize(output)
8
+ def initialize(loggregator_host, user_token, output)
8
9
  @output = output
10
+ @loggregator_host = loggregator_host
11
+ @user_token = user_token
9
12
  end
10
13
 
11
- def listen(loggregator_host, space_id, app_id, user_token)
12
- websocket_address = "wss://#{loggregator_host}:4443/tail/spaces/#{space_id}"
13
- websocket_address += "/apps/#{app_id}" if app_id
14
+ def listen(query_params)
15
+ websocket_address = "wss://#{loggregator_host}:4443/tail/?#{hash_to_query(query_params)}"
14
16
 
15
17
  EM.run {
16
18
  ws = Faye::WebSocket::Client.new(websocket_address, nil, :headers => {"Origin" => "http://localhost", "Authorization" => user_token})
@@ -24,7 +26,7 @@ module TailCfPlugin
24
26
 
25
27
  ws.on :message do |event|
26
28
  received_message = LogMessage.decode(event.data.pack("C*"))
27
- output.puts([received_message.app_id, received_message.source_id, received_message.message_type_name, received_message.message].join(" "))
29
+ MessageWriter.write(output, received_message)
28
30
  end
29
31
 
30
32
  ws.on :error do |event|
@@ -40,12 +42,40 @@ module TailCfPlugin
40
42
  }
41
43
  end
42
44
 
45
+ def dump_messages(query_params)
46
+ uri = URI.parse("https://#{loggregator_host}/dump/?#{hash_to_query(query_params)}")
47
+ http = Net::HTTP.new(uri.host, uri.port)
48
+ http.use_ssl = true
49
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
50
+
51
+ request = Net::HTTP::Get.new(uri.request_uri)
52
+ request['Authorization'] = user_token
53
+
54
+ response = http.request(request)
55
+
56
+ return [] unless response.code == "200"
57
+
58
+ response_bytes = StringIO.new(response.body)
59
+ messages = []
60
+ while len = response_bytes.read(4)
61
+ len = len.unpack("N")[0] # 32-bit length, BigEndian stylie
62
+ record = response_bytes.read(len) # This returns a string even if len is 0.
63
+ msg = LogMessage.decode(record)
64
+ messages << msg
65
+ end
66
+ messages
67
+ end
68
+
43
69
  private
44
70
 
45
71
  def keep_alive_interval
46
72
  25
47
73
  end
48
74
 
49
- attr_reader :output
75
+ def hash_to_query(hash)
76
+ return URI.encode(hash.map{|k,v| "#{k}=#{v}"}.join("&"))
77
+ end
78
+
79
+ attr_reader :output, :loggregator_host, :user_token
50
80
  end
51
81
  end
@@ -0,0 +1,5 @@
1
+ module MessageWriter
2
+ def self.write(output, message)
3
+ output.puts([message.app_id, message.source_id, message.message_type_name, message.message].join(" "))
4
+ end
5
+ end
@@ -2,28 +2,44 @@ require 'cf'
2
2
 
3
3
  module TailCfPlugin
4
4
  require 'tail-cf-plugin/loggregator_client'
5
+ require 'tail-cf-plugin/log_target'
6
+ require 'tail-cf-plugin/message_writer'
5
7
 
6
8
  class Plugin < CF::CLI
7
9
  include LoginRequirements
8
10
 
9
- desc "Tail logs for CF applications or spaces"
11
+ desc "Tail or dump logs for CF applications or spaces"
10
12
  group :apps
11
13
  input :app, :desc => "App to tail logs from", :argument => :optional, :from_given => by_name(:app)
12
14
  input :space, :type => :boolean, :desc => "Logs of all apps in the current space", :default => false
15
+ input :org, :type => :boolean, :desc => "Logs of all apps and spaces in the current organization", :default => false
16
+ input :recent, :type => :boolean, :desc => "Dump recent logs instead of tailing", :default => false
13
17
 
14
18
  def logs
15
- if input[:space]
16
- app_guid = nil
17
- else
18
- unless input[:app]
19
- Mothership::Help.command_help(@@commands[:logs])
20
- fail "Please provide an application to log or call with --space"
21
- end
22
- app_guid = input[:app].guid
19
+ guids = [client.current_organization.guid, client.current_space.guid, input[:app].try(:guid)]
20
+
21
+ log_target = LogTarget.new(input[:org], input[:space], guids)
22
+
23
+ if log_target.ambiguous?
24
+ Mothership::Help.command_help(@@commands[:logs])
25
+ fail "Please provide either --space or --org, but not both."
26
+ end
27
+
28
+ unless log_target.valid?
29
+ Mothership::Help.command_help(@@commands[:logs])
30
+ fail "Please provide an application to log."
23
31
  end
24
32
 
25
- loggregator_client = LoggregatorClient.new(STDOUT)
26
- loggregator_client.listen(loggregator_host, client.current_space.guid, app_guid, client.token.auth_header)
33
+ loggregator_client = LoggregatorClient.new(loggregator_host, client.token.auth_header, STDOUT)
34
+
35
+ if input[:recent]
36
+ loggregator_client.dump_messages(log_target.query_params).each do |m|
37
+ MessageWriter.write(STDOUT, m)
38
+ end
39
+
40
+ else
41
+ loggregator_client.listen(log_target.query_params)
42
+ end
27
43
  end
28
44
 
29
45
  ::ManifestsPlugin.default_to_app_from_manifest(:logs, false)
@@ -34,6 +50,5 @@ module TailCfPlugin
34
50
  target_base = client.target.sub(/^https?:\/\/([^\.]+\.)?(.+)\/?/, '\2')
35
51
  "loggregator.#{target_base}"
36
52
  end
37
-
38
53
  end
39
54
  end
@@ -23,6 +23,8 @@ class LogMessage
23
23
  required :app_id, :string, 4
24
24
  required :source_type, LogMessage::SourceType, 5
25
25
  optional :source_id, :string, 6
26
+ optional :space_id, :string, 7
27
+ required :organization_id, :string, 8
26
28
 
27
29
  def message_type_name
28
30
  {MessageType::OUT => 'STDOUT', MessageType::ERR => 'STDERR'}[message_type]
@@ -20,4 +20,6 @@ message LogMessage {
20
20
  required string app_id = 4;
21
21
  required SourceType source_type = 5;
22
22
  optional string source_id = 6;
23
+ optional string space_id = 7;
24
+ required string organization_id = 8;
23
25
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tail-cf-plugin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.20.pre
4
+ version: 0.0.21.pre
5
5
  prerelease: 7
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-08 00:00:00.000000000 Z
12
+ date: 2013-08-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: cf
@@ -72,7 +72,9 @@ executables: []
72
72
  extensions: []
73
73
  extra_rdoc_files: []
74
74
  files:
75
+ - lib/tail-cf-plugin/log_target.rb
75
76
  - lib/tail-cf-plugin/loggregator_client.rb
77
+ - lib/tail-cf-plugin/message_writer.rb
76
78
  - lib/tail-cf-plugin/plugin.rb
77
79
  - vendor/log_message/log_message.pb.rb
78
80
  - vendor/log_message/log_message.proto