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

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.
@@ -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