nfagent 0.9.19 → 0.9.20

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,4 +1,4 @@
1
- == 0.0.1 2009-09-22
1
+ === 0.0.1 2011-02-03
2
2
 
3
3
  * 1 major enhancement:
4
4
  * Initial release
data/Manifest.txt CHANGED
@@ -1,29 +1,45 @@
1
+ History.txt
2
+ Manifest.txt
3
+ PostInstall.txt
4
+ README.rdoc
1
5
  Rakefile
6
+ script/console
7
+ script/destroy
8
+ script/generate
9
+ test/test_chunk.rb
10
+ test/test_chunk_handler.rb
11
+ test/test_client.rb
12
+ test/test_config.rb
13
+ test/test_helper.rb
14
+ test/test_mapper_proxy.rb
15
+ test/test_nfagent.rb
16
+ test/test_payload.rb
17
+ test/test_plugin.rb
18
+ test/config
19
+ test/plugins/my_mapper.rb
2
20
  lib/nfagent.rb
3
21
  lib/nfagent
4
- lib/nfagent/cli.rb
5
22
  lib/nfagent/base64.rb
6
- lib/nfagent/encoder.rb
7
- lib/nfagent/server.rb
8
- lib/nfagent/chunk_handler.rb
9
- lib/nfagent/log.rb
10
- lib/nfagent/info.rb
11
- lib/nfagent/event.rb
12
- lib/nfagent/payload.rb
13
- lib/nfagent/poller.rb
14
23
  lib/nfagent/chunk.rb
24
+ lib/nfagent/chunk_handler.rb
25
+ lib/nfagent/cli.rb
15
26
  lib/nfagent/client.rb
16
27
  lib/nfagent/client_response.rb
17
28
  lib/nfagent/config.rb
29
+ lib/nfagent/encoder.rb
30
+ lib/nfagent/event.rb
31
+ lib/nfagent/info.rb
32
+ lib/nfagent/log.rb
33
+ lib/nfagent/mapper_proxy.rb
34
+ lib/nfagent/payload.rb
35
+ lib/nfagent/plugin.rb
36
+ lib/nfagent/poller.rb
37
+ lib/nfagent/server.rb
38
+ lib/nfagent/submitter.rb
18
39
  lib/nfagent/tail.rb
19
40
  lib/nfagent/tests.rb
20
- lib/nfagent/submitter.rb
21
41
  bin/nfagent
22
42
  bin/squid_log_writer
23
- PostInstall.txt
24
- History.txt
25
- Manifest.txt
26
- README.txt
27
43
  nfagent.conf
28
44
  nfagent.init.ubuntu.txt
29
45
  nfagent.init.redhat.txt
data/PostInstall.txt CHANGED
@@ -1 +1,7 @@
1
+
1
2
  For more information on nfagent, see http://nfagent.rubyforge.org
3
+
4
+ NOTE: Change this information in PostInstall.txt
5
+ You can also delete it if you don't want it.
6
+
7
+
@@ -1,40 +1,32 @@
1
- = NetFox Agent
1
+ = nfagent
2
2
 
3
- * http://netfox.com
3
+ * http://github.com/#{github_username}/#{project_name}
4
4
 
5
5
  == DESCRIPTION:
6
6
 
7
- Logging Agent for NetFox Online
7
+ FIX (describe your package)
8
8
 
9
9
  == FEATURES/PROBLEMS:
10
10
 
11
+ * FIX (list of features or problems)
11
12
 
12
13
  == SYNOPSIS:
13
14
 
15
+ FIX (code sample of usage)
14
16
 
15
17
  == REQUIREMENTS:
16
18
 
17
- * Event Machine
18
- * SV Util
19
+ * FIX (list of requirements)
19
20
 
20
21
  == INSTALL:
21
22
 
22
- sudo gem install nfagent
23
-
24
- == DEVELOPERS:
25
-
26
- After checking out the source, run:
27
-
28
- $ rake newb
29
-
30
- This task will install any missing dependencies, run the tests/specs,
31
- and generate the RDoc.
23
+ * FIX (sudo gem install, anything else)
32
24
 
33
25
  == LICENSE:
34
26
 
35
27
  (The MIT License)
36
28
 
37
- Copyright (c) 2010 FIX
29
+ Copyright (c) 2011 FIXME full name
38
30
 
39
31
  Permission is hereby granted, free of charge, to any person obtaining
40
32
  a copy of this software and associated documentation files (the
@@ -53,4 +45,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
53
45
  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
54
46
  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
55
47
  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
56
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
48
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile CHANGED
@@ -1,31 +1,28 @@
1
- %w[rubygems rake rake/clean hoe fileutils newgem rubigen].each { |f| require f }
2
- require File.dirname(__FILE__) + '/lib/nfagent'
1
+ require 'rubygems'
2
+ gem 'hoe', '>= 2.1.0'
3
+ require 'hoe'
4
+ require 'fileutils'
5
+ require './lib/nfagent'
6
+
7
+ Hoe.plugin :newgem
8
+ # Hoe.plugin :website
9
+ # Hoe.plugin :cucumberfeatures
3
10
 
4
11
  # Generate all the Rake tasks
5
12
  # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
- $hoe = Hoe.spec('nfagent') do |p|
7
- p.version = NFAgent::VERSION
8
- p.summary = "Logging Agent for NetFox Online"
9
- p.developer('Daniel Draper', 'daniel@netfox.com')
10
- p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
11
- p.post_install_message = 'PostInstall.txt'
12
- p.rubyforge_name = p.name
13
- p.extra_deps = [
14
- ['svutil','>= 0.0.12'], ['eventmachine', '>= 0.12.8']
15
- ]
16
- p.extra_dev_deps = [
17
- ['newgem', ">= #{::Newgem::VERSION}"]
13
+ $hoe = Hoe.spec 'nfagent' do
14
+ self.developer('Daniel Draper', 'daniel@netfox.com')
15
+ self.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
16
+ self.rubyforge_name = self.name # TODO this is default value
17
+ self.extra_deps = [
18
+ ['svutil','>= 0.0.13'], ['eventmachine', '>= 0.12.8'], ['squiggle']
18
19
  ]
19
- p.clean_globs |= %w[**/.DS_Store tmp *.log]
20
- path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
21
- p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
22
- p.rsync_args = '-av --delete --ignore-errors'
23
- p.readme_file = "README.txt"
24
- p.spec_extras[:default_executable] = 'nfagent'
20
+
25
21
  end
26
22
 
27
- require 'newgem/tasks' # load /tasks/*.rake
23
+ require 'newgem/tasks'
28
24
  Dir['tasks/**/*.rake'].each { |t| load t }
29
25
 
30
26
  # TODO - want other tests/tasks run by default? Add them to the list
27
+ # remove_task :default
31
28
  # task :default => [:spec, :features]
data/lib/nfagent.rb CHANGED
@@ -3,6 +3,7 @@ $:.unshift(File.dirname(__FILE__)) unless
3
3
 
4
4
  require 'rubygems'
5
5
  require 'svutil'
6
+ require 'squiggle'
6
7
 
7
8
  require 'fileutils'
8
9
  require 'logger'
@@ -17,6 +18,8 @@ require 'nfagent/chunk'
17
18
  require 'nfagent/client'
18
19
  require 'nfagent/client_response'
19
20
  require 'nfagent/chunk_handler'
21
+ require 'nfagent/mapper_proxy'
22
+ require 'nfagent/plugin'
20
23
  require 'nfagent/submitter'
21
24
  require 'nfagent/encoder'
22
25
  require 'nfagent/config'
@@ -31,5 +34,5 @@ require 'nfagent/cli'
31
34
  require 'nfagent/tests'
32
35
 
33
36
  module NFAgent
34
- VERSION = '0.9.19'
37
+ VERSION = '0.9.20'
35
38
  end
data/lib/nfagent/chunk.rb CHANGED
@@ -2,44 +2,54 @@ require 'zlib'
2
2
  require 'digest'
3
3
 
4
4
  module NFAgent
5
- class Chunk
5
+ class ChunkExpired < StandardError; end
6
+ class ChunkFull < StandardError; end
7
+ class DayBoundary < StandardError; end
8
+
9
+ class Chunk < Array
6
10
  attr_reader :created_at
11
+ attr_reader :max_size
7
12
 
8
- ::DEFAULT_TIME_OUT = 60
13
+ DEFAULT_MAX_SIZE = 500
9
14
 
10
- def initialize(max_size = 500)
15
+ def initialize(max_size = DEFAULT_MAX_SIZE)
11
16
  @max_size = max_size
12
17
  @created_at = Time.now
13
- @array = []
14
- @submitter = Submitter.new(Config.client_key)
15
18
  end
16
19
 
17
20
  def <<(line)
18
- @array << line
21
+ raise ChunkExpired if expired?
22
+ raise ChunkFull if full?
23
+ raise DayBoundary if Time.now.day != self.created_at.day
24
+ super(line)
19
25
  end
20
26
 
21
27
  def full?
22
- @array.size >= @max_size
28
+ self.size >= @max_size
23
29
  end
24
30
 
25
31
  def expired?
26
- (Time.now - @created_at > ::DEFAULT_TIME_OUT) && !@array.empty?
32
+ (Time.now - @created_at > Config.chunk_time_out) && !self.empty?
27
33
  end
28
34
 
29
- # TODO: Is this the right place for compression, encoding and check summing? Perhaps it should go into the submitter to that it can be deferred
30
- def dump
35
+ def dump(key = nil)
31
36
  Payload.new do |payload|
32
- Log.info("Dumping payload from chunk (#{@array.size} lines)")
33
- payload.line_count = @array.size
37
+ Log.info("Dumping payload from chunk (#{self.size} lines)")
38
+ payload.line_count = self.size
34
39
  payload.chunk_expired = expired?
35
- payload.data = Encoder.encode64url(Zlib::Deflate.deflate(@array.join("\n"), Zlib::BEST_COMPRESSION))
40
+ payload.key = key
41
+ payload.data = Encoder.encode64url(Zlib::Deflate.deflate(self.join("\n"), Zlib::BEST_COMPRESSION))
36
42
  payload.checksum = Digest::SHA1.hexdigest(payload.data)
37
43
  end
38
44
  end
39
45
 
40
- def clear
41
- @array.clear
42
- @created_at = Time.now
46
+ def submit(key = nil)
47
+ submitter = Submitter.new(self.dump(key))
48
+ submitter.errback { |payload|
49
+ payload.write_to_disk(Config.dump_dir)
50
+ }
51
+ submitter.perform
52
+ # Callback and remove from chunk group
43
53
  end
44
54
  end
45
55
  end
@@ -1,40 +1,65 @@
1
1
  module NFAgent
2
2
  class ChunkHandler
3
3
 
4
- # TODO: Rename this to Controller later
5
- def initialize(chunk_size = 500)
6
- @chunk = Chunk.new(chunk_size)
4
+ attr_accessor :chunk_group
5
+
6
+ def initialize(options = {})
7
+ @chunk_size = options[:chunk_size] || 500
8
+ @parser = options[:parser] || Squiggle::SquidStandardParser.new(Config.time_zone)
9
+ @chunk_group = {}
10
+ class << @chunk_group
11
+ def fetch!(key, new_chunk)
12
+ if self.has_key?(key)
13
+ self.fetch(key)
14
+ else
15
+ self[key] = new_chunk
16
+ new_chunk
17
+ end
18
+ end
19
+ end
7
20
  end
8
21
 
9
22
  def append(line)
10
- # if current day is > day of last entry on current_chunk
11
- # then submit and reset the chunk before adding the line
12
- current_day = Time.now.day
13
- if current_day != @chunk.created_at.day
14
- Log.info("Expiring chunk due to date rollover")
15
- reset_chunk
23
+ if Config.parse == 'locally'
24
+ parsed = @parser.parse(line)
25
+ return if parsed.invalid?
26
+ if Config.mode == 'multi'
27
+ key = MapperProxy.find_account_id(parsed.username, parsed.client_ip)
28
+ # TODO: Still appending line as string until Server API has been updated
29
+ return append2(line, key)
30
+ end
31
+ end
32
+ # TODO: rename append2
33
+ append2(line)
34
+ end
35
+
36
+ def append2(line, key = nil)
37
+ key ||= 'all'
38
+ begin
39
+ chunk = @chunk_group.fetch!(key, Chunk.new(@chunk_size))
40
+ chunk << line
41
+ rescue ChunkExpired, ChunkFull
42
+ reset_chunk(key)
16
43
  end
17
- @chunk << line
18
44
  end
19
45
 
20
46
  def check_full_or_expired
21
- if @chunk.full?
22
- Log.info("Chunk Full: Resetting...")
23
- reset_chunk
24
- elsif @chunk.expired?
25
- Log.info("Chunk Expired: Resetting...")
26
- reset_chunk
47
+ @chunk_group.each_pair do |key, chunk|
48
+ if chunk.full?
49
+ Log.info("Chunk Full: Resetting...")
50
+ reset_chunk(key)
51
+ elsif chunk.expired?
52
+ Log.info("Chunk Expired: Resetting...")
53
+ reset_chunk(key)
54
+ end
27
55
  end
28
56
  end
29
57
 
30
58
  private
31
- def reset_chunk
32
- submitter = Submitter.new(@chunk.dump)
33
- submitter.errback { |payload|
34
- payload.write_to_disk(Config.dump_dir)
35
- }
36
- @chunk.clear
37
- submitter.perform
59
+ def reset_chunk(key = nil)
60
+ key ||= 'all'
61
+ chunk = @chunk_group.delete(key)
62
+ chunk.submit
38
63
  end
39
64
  end
40
65
  end
@@ -1,6 +1,6 @@
1
1
  module NFAgent
2
2
  class Client
3
- SERVICE_HOST = "collector.service.netfox.com"
3
+ SERVICE_HOST = "collector.service.netfox.com"
4
4
 
5
5
  def self.post(end_point, data_hash)
6
6
  proxy_class = Net::HTTP::Proxy(Config.http_proxy_host, Config.http_proxy_port, Config.http_proxy_user, Config.http_proxy_password)
@@ -8,7 +8,7 @@ module NFAgent
8
8
  proxy_class.start(SERVICE_HOST, 80) do |http|
9
9
  http.read_timeout = 120 # 2 minutes TODO: Make this a config option with 120 as default
10
10
  req = Net::HTTP::Post.new("/#{end_point}")
11
- req.set_form_data(data_hash.merge("key" => Config.client_key))
11
+ req.set_form_data({"key" => Config.client_key}.merge(data_hash))
12
12
  ClientResponse.new do |resp|
13
13
  resp.response, resp.message = http.request(req)
14
14
  end
@@ -8,11 +8,41 @@ module NFAgent
8
8
  @@test_mode
9
9
  end
10
10
 
11
+ # Config Options
12
+ # client_key: String, the access key for the client (for the account in normal mode or for a partner in multi mode)
13
+ # dump_dir: String, the directory path of a local spool location
14
+ # pid_file: String, path of process ID file
15
+ # mode: (optional, default: 'normal') String, either 'normal' or 'multi' - can be left blank
16
+ # mapping: Class, this is a plugin class which must be stored in a file in the directory /etc/nfagent/plugins/
17
+ # parse: (optional, default: 'remotely'): String, either 'remotely' or 'locally'
18
+ #
11
19
  class << self
20
+ def set_defaults
21
+ default('mode', 'normal')
22
+ default('parse', 'remotely')
23
+ default('chunk_time_out', 60)
24
+ default('time_zone', 'UTC')
25
+ default('plugin_directory', '/etc/nfagent/plugins/')
26
+ end
27
+
12
28
  def validate
13
29
  unless dump_dir and File.exists?(dump_dir) and File.directory?(dump_dir)
14
30
  raise "Dump dir (#{dump_dir}) must exist and be a directory"
15
31
  end
32
+ # Mode
33
+ unless %w(normal multi).include?(mode)
34
+ raise "Invalid mode: must be one of 'normal' or 'multi'"
35
+ end
36
+ if mode == 'multi' && mapper.blank?
37
+ raise "Multi mode requires a mapper to be set"
38
+ end
39
+ if mode == 'multi' && parse != 'locally'
40
+ raise "Multi mode requires that parsing be done locally (set parse = 'locally')"
41
+ end
42
+ # Parse
43
+ unless %w(remotely locally).include?(parse)
44
+ raise "Invalid parse option: Must be one of 'remotely' or 'locally'"
45
+ end
16
46
  super
17
47
  end
18
48
 
@@ -30,6 +60,9 @@ module NFAgent
30
60
  opts.on("-T", "--test", "Run connection tests") do
31
61
  @@test_mode = true
32
62
  end
63
+ opts.on("-P", "--parse", "Parse locally before submitting") do
64
+ Config.parse_locally = true
65
+ end
33
66
  end
34
67
  end
35
68
  end
@@ -0,0 +1,18 @@
1
+ module NFAgent
2
+ class MapperProxy
3
+ class << self
4
+ def instance
5
+ return @instance if @instance
6
+ raise "No Mapper Set" if Config.mapper.blank?
7
+ @instance = Config.mapper.constantize.new
8
+ end
9
+
10
+ # TODO: Can we delegate?
11
+ def find_account_id(username, client_ip)
12
+ instance.find_account_id(username, client_ip)
13
+ end
14
+
15
+ # TODO: before shutdown
16
+ end
17
+ end
18
+ end
@@ -1,6 +1,6 @@
1
1
 
2
2
  module NFAgent
3
- class Payload < Struct.new(:data, :checksum, :filename, :line_count, :chunk_expired)
3
+ class Payload < Struct.new(:data, :checksum, :filename, :line_count, :chunk_expired, :key)
4
4
  def initialize
5
5
  yield self
6
6
  end
@@ -23,12 +23,14 @@ module NFAgent
23
23
  end
24
24
 
25
25
  def to_hash
26
- {
26
+ ret = {
27
27
  "payload" => self.data,
28
28
  "checksum" => self.checksum,
29
29
  "line_count" => self.line_count,
30
30
  "chunk_expired" => self.chunk_expired
31
31
  }
32
+ ret["key"] = self.key unless self.key.blank?
33
+ ret
32
34
  end
33
35
 
34
36
  def write_to_disk(directory)
@@ -0,0 +1,13 @@
1
+ module NFAgent
2
+ class Plugin
3
+ class << self
4
+ def load_plugins
5
+ unless Config.plugin_directory.blank?
6
+ Dir.glob(File.join(Config.plugin_directory, "*.rb")).each do |file|
7
+ load(file)
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -2,6 +2,8 @@ module NFAgent
2
2
  class Server
3
3
  def run
4
4
  Log.info("Starting up")
5
+ NFAgent::Plugin.load_plugins
6
+
5
7
  chunk_handler = ChunkHandler.new
6
8
  poller = Poller.new
7
9
 
data/script/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/nfagent.rb'}"
9
+ puts "Loading nfagent gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
data/test/config ADDED
@@ -0,0 +1,5 @@
1
+ client_key = 1234
2
+ dump_dir = test/sandbox/dumps
3
+ log_file = test/sandbox/debug
4
+ pid_file = test/sandbox/nfagent.pid
5
+ plugin_directory = test/plugins/
@@ -0,0 +1,17 @@
1
+ class MyMapper
2
+ def initialize
3
+ @hash = {
4
+ 'dan' => 'acme',
5
+ 'paul' => 'jetson',
6
+ 'mike' => 'acme'
7
+ }
8
+ end
9
+
10
+ def before_shutdown
11
+ # Put any cleanup code in here
12
+ end
13
+
14
+ def find_account_id(username, client_ip)
15
+ @hash[username]
16
+ end
17
+ end
@@ -0,0 +1,80 @@
1
+
2
+ require 'test/test_helper'
3
+
4
+ class TestChunk < ActiveSupport::TestCase
5
+ setup do
6
+ NFAgent::Config.config_file = "test/config"
7
+ NFAgent::Config.load_and_parse
8
+ @logline = "1253604221 19 127.0.0.1 TCP_MISS/200 562 GET http://www.gravatar.com/blavatar/e81cfb9068d04d1cfd598533bb380e1f?s=16&d=http://s.wordpress.com/favicon.ico - NONE/- text/html"
9
+ end
10
+
11
+ test "initialize" do
12
+ chunk = NFAgent::Chunk.new
13
+ assert_equal 500, chunk.max_size
14
+ chunk = NFAgent::Chunk.new(600)
15
+ assert_equal 600, chunk.max_size
16
+ end
17
+
18
+ test "full" do
19
+ chunk = NFAgent::Chunk.new(20)
20
+ 19.times do
21
+ chunk << @logline
22
+ end
23
+ assert !chunk.full?
24
+ chunk << @logline
25
+ assert chunk.full?
26
+ assert_raises(NFAgent::ChunkFull) { chunk << @logline }
27
+ end
28
+
29
+ test "won't expire if empty" do
30
+ NFAgent::Config.chunk_time_out = 1
31
+ NFAgent::Config.validate
32
+ chunk = NFAgent::Chunk.new
33
+ assert !chunk.expired?
34
+ Timecop.freeze(Time.now + 61) do
35
+ assert !chunk.expired?
36
+ end
37
+ end
38
+
39
+ test "expired" do
40
+ chunk = NFAgent::Chunk.new
41
+ chunk << @logline
42
+ assert !chunk.expired?
43
+ Timecop.freeze(Time.now + 61) do
44
+ assert chunk.expired?
45
+ assert_raises(NFAgent::ChunkExpired) { chunk << @logline }
46
+ end
47
+ end
48
+
49
+ test "day boundary" do
50
+ d = Date.today
51
+ Timecop.travel(Time.local(2011, 1, 10, 23, 59, 58)) do
52
+ chunk = NFAgent::Chunk.new
53
+ Timecop.travel(Time.local(2011, 1, 11, 0, 0, 10)) do
54
+ assert_raises(NFAgent::DayBoundary) { chunk << @logline }
55
+ end
56
+ end
57
+ end
58
+
59
+ test "submit" do
60
+ NFAgent::Submitter.any_instance.expects(:perform)
61
+ chunk = NFAgent::Chunk.new
62
+ chunk.submit
63
+ end
64
+
65
+ test "dump" do
66
+ Zlib::Deflate.expects(:deflate).returns("x\234\313\316*/\314HO-\312N\317(J\005\000&~\005u").times(2)
67
+ chunk = NFAgent::Chunk.new
68
+ chunk << @logline
69
+ payload = chunk.dump
70
+ assert_equal 1, payload.line_count
71
+ assert_instance_of String, payload.data
72
+ # Dump with key
73
+ payload = chunk.dump('acme')
74
+ assert_equal 'acme', payload.key
75
+ end
76
+
77
+ test "dump from LogLine" do
78
+ flunk
79
+ end
80
+ end
@@ -0,0 +1,97 @@
1
+
2
+ require 'test/test_helper'
3
+
4
+ class TestChunkHandler < ActiveSupport::TestCase
5
+ setup do
6
+ NFAgent::Config.config_file = "test/config"
7
+ NFAgent::Config.load_and_parse
8
+ NFAgent::Config.plugin_directory = File.dirname(__FILE__) + '/../test/plugins/'
9
+ NFAgent::Plugin.load_plugins
10
+ @logline = "1253604221 19 127.0.0.1 TCP_MISS/200 562 GET http://www.gravatar.com/blavatar/e81cfb9068d04d1cfd598533bb380e1f?s=16&d=http://s.wordpress.com/favicon.ico dan NONE/- text/html"
11
+ @logline2 = "1253604221 19 127.0.0.1 TCP_MISS/200 562 GET http://www.gravatar.com/blavatar/e81cfb9068d04d1cfd598533bb380e1f?s=16&d=http://s.wordpress.com/favicon.ico paul NONE/- text/html"
12
+ end
13
+
14
+ test "append line" do
15
+ chunk_handler = NFAgent::ChunkHandler.new
16
+ chunk_handler.append(@logline)
17
+ assert_equal 1, chunk_handler.chunk_group['all'].size
18
+ assert_instance_of String, chunk_handler.chunk_group['all'][-1]
19
+ end
20
+
21
+ test "append with local parsing" do
22
+ NFAgent::Config.parse = 'locally'
23
+ chunk_handler = NFAgent::ChunkHandler.new
24
+ chunk_handler.append(@logline)
25
+ assert_equal 1, chunk_handler.chunk_group['all'].size
26
+ assert_instance_of Squiggle::LogLine, chunk_handler.chunk_group['all'][-1]
27
+ end
28
+
29
+ test "append with multi" do
30
+ NFAgent::Config.parse = 'locally'
31
+ NFAgent::Config.mode = 'multi'
32
+ NFAgent::Config.mapper = 'MyMapper'
33
+ NFAgent::Config.validate
34
+ chunk_handler = NFAgent::ChunkHandler.new
35
+ chunk_handler.append(@logline)
36
+ assert chunk_handler.chunk_group.has_key?('acme')
37
+ assert_equal 1, chunk_handler.chunk_group['acme'].size
38
+ chunk_handler.append(@logline2)
39
+ assert chunk_handler.chunk_group.has_key?('acme')
40
+ assert chunk_handler.chunk_group.has_key?('jetson')
41
+ assert_equal 1, chunk_handler.chunk_group['acme'].size
42
+ assert_equal 1, chunk_handler.chunk_group['jetson'].size
43
+ end
44
+
45
+ test "reset chunk after expiry" do
46
+ NFAgent::Config.parse = 'locally'
47
+ NFAgent::Config.mode = 'multi'
48
+ NFAgent::Config.mapper = 'MyMapper'
49
+ NFAgent::Config.validate
50
+ NFAgent::Submitter.any_instance.expects(:perform).times(2)
51
+ chunk_handler = NFAgent::ChunkHandler.new
52
+ chunk_handler.append(@logline)
53
+ Timecop.travel(30) do
54
+ chunk_handler.append(@logline2)
55
+ assert_equal 1, chunk_handler.chunk_group['acme'].size
56
+ assert_equal 1, chunk_handler.chunk_group['jetson'].size
57
+
58
+ Timecop.travel(31) do
59
+ chunk_handler.check_full_or_expired
60
+ assert !chunk_handler.chunk_group.has_key?('acme')
61
+ assert_equal 1, chunk_handler.chunk_group['jetson'].size
62
+
63
+ Timecop.travel(31) do
64
+ chunk_handler.check_full_or_expired
65
+ assert !chunk_handler.chunk_group.has_key?('acme')
66
+ assert !chunk_handler.chunk_group.has_key?('jestson')
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ test "reset chunk after full wuth check_full_or_expired" do
73
+ NFAgent::Config.parse = 'locally'
74
+ NFAgent::Config.mode = 'multi'
75
+ NFAgent::Config.mapper = 'MyMapper'
76
+ NFAgent::Config.validate
77
+ NFAgent::Submitter.any_instance.expects(:perform).times(2)
78
+ chunk_handler = NFAgent::ChunkHandler.new(:chunk_size => 10)
79
+ 9.times { chunk_handler.append(@logline) }
80
+ 9.times { chunk_handler.append(@logline2) }
81
+ assert_equal 9, chunk_handler.chunk_group['acme'].size
82
+ assert_equal 9, chunk_handler.chunk_group['jetson'].size
83
+ chunk_handler.append(@logline)
84
+ chunk_handler.check_full_or_expired
85
+ assert !chunk_handler.chunk_group.has_key?('acme')
86
+ chunk_handler.append(@logline2)
87
+ chunk_handler.check_full_or_expired
88
+ assert !chunk_handler.chunk_group.has_key?('jetson')
89
+ end
90
+
91
+ test "fail an invalid logline in local parse mode" do
92
+ NFAgent::Config.parse = 'locally'
93
+ chunk_handler = NFAgent::ChunkHandler.new
94
+ chunk_handler.append("") # Invalid logline
95
+ assert chunk_handler.chunk_group['all'].nil?
96
+ end
97
+ end
@@ -0,0 +1,20 @@
1
+
2
+ require 'test/test_helper'
3
+
4
+ class TestClient < ActiveSupport::TestCase
5
+ setup do
6
+ end
7
+
8
+ test "post data with configured client key" do
9
+ Net::HTTP::Post.any_instance.expects(:set_form_data).with({ 'payload' => 'data', 'checksum' => 'checksum', 'line_count' => 10, 'chunk_expired' => false, 'key' => '1234' })
10
+ hash = { 'payload' => 'data', 'checksum' => 'checksum', 'line_count' => 10, 'chunk_expired' => false }
11
+ NFAgent::Client.post(:collector, hash)
12
+ end
13
+
14
+ test "post data with key passed in data hash" do
15
+ Net::HTTP::Post.any_instance.expects(:set_form_data).with({ 'payload' => 'data', 'checksum' => 'checksum', 'line_count' => 10, 'chunk_expired' => false, 'key' => 'abcd' })
16
+ hash = { 'payload' => 'data', 'checksum' => 'checksum', 'line_count' => 10, 'chunk_expired' => false, 'key' => 'abcd' }
17
+ NFAgent::Client.post(:collector, hash)
18
+ end
19
+
20
+ end
@@ -0,0 +1,40 @@
1
+
2
+ require 'test/test_helper'
3
+
4
+ class TestConfig < ActiveSupport::TestCase
5
+ setup do
6
+ NFAgent::Config.config_file = "test/config"
7
+ NFAgent::Config.load_and_parse
8
+ end
9
+
10
+ test "defaults" do
11
+ assert_equal "normal", NFAgent::Config.mode
12
+ assert_equal "remotely", NFAgent::Config.parse
13
+ assert_equal 60, NFAgent::Config.chunk_time_out
14
+ assert_equal 'UTC', NFAgent::Config.time_zone
15
+ assert_equal '/etc/nfagent/plugins/', NFAgent::Config.plugin_directory
16
+ end
17
+
18
+ test "validates valid mode" do
19
+ NFAgent::Config.mode = 'some stupid thing'
20
+ assert_raises(RuntimeError) { NFAgent::Config.validate }
21
+ end
22
+
23
+ test "validates mapping with multi" do
24
+ NFAgent::Config.mode = 'multi'
25
+ assert_raises(RuntimeError) { NFAgent::Config.validate }
26
+ NFAgent::Config.mapper = 'AccountMapper'
27
+ assert_raises(RuntimeError) { NFAgent::Config.validate }
28
+ NFAgent::Config.parse = 'locally'
29
+ assert NFAgent::Config.validate
30
+ end
31
+
32
+ test "validates valid parse option" do
33
+ NFAgent::Config.parse = 'some stupid thing'
34
+ assert_raises(RuntimeError) { NFAgent::Config.validate }
35
+ NFAgent::Config.parse = 'locally'
36
+ assert NFAgent::Config.validate
37
+ NFAgent::Config.parse = 'remotely'
38
+ assert NFAgent::Config.validate
39
+ end
40
+ end
@@ -0,0 +1,6 @@
1
+
2
+ require 'mocha'
3
+ require 'timecop'
4
+ require 'active_support'
5
+ require File.dirname(__FILE__) + '/../lib/nfagent'
6
+
@@ -0,0 +1,20 @@
1
+
2
+ require 'test/test_helper'
3
+
4
+ class TestMapperProxy < ActiveSupport::TestCase
5
+ setup do
6
+ NFAgent::Config.plugin_directory = File.dirname(__FILE__) + '/../test/plugins/'
7
+ end
8
+
9
+ test "instantiate just once" do
10
+ MyMapper.expects(:new).at_most_once
11
+ NFAgent::Config.mapper = nil
12
+ NFAgent::MapperProxy.instance
13
+ NFAgent::MapperProxy.instance
14
+ NFAgent::MapperProxy.instance
15
+ end
16
+
17
+ test "mapper method" do
18
+ assert_equal 'acme', NFAgent::MapperProxy.find_account_id('dan', '192.168.0.10')
19
+ end
20
+ end
@@ -0,0 +1,8 @@
1
+
2
+ require 'test/test_helper'
3
+
4
+ class NFAgentTest < ActiveSupport::TestCase
5
+ test "just return true" do
6
+ assert true
7
+ end
8
+ end
@@ -0,0 +1,26 @@
1
+
2
+ require 'test/test_helper'
3
+
4
+ class TestPayload < ActiveSupport::TestCase
5
+ setup do
6
+ end
7
+
8
+ test "to_hash" do
9
+ payload = NFAgent::Payload.new do |p|
10
+ p.data = "data"
11
+ p.checksum = "checksum"
12
+ p.line_count = 10
13
+ p.chunk_expired = false
14
+ end
15
+ assert_equal({ 'payload' => 'data', 'checksum' => 'checksum', 'line_count' => 10, 'chunk_expired' => false }, payload.to_hash)
16
+ # Check key
17
+ payload = NFAgent::Payload.new do |p|
18
+ p.data = "data"
19
+ p.checksum = "checksum"
20
+ p.line_count = 10
21
+ p.chunk_expired = false
22
+ p.key = '1234'
23
+ end
24
+ assert_equal({ 'payload' => 'data', 'checksum' => 'checksum', 'line_count' => 10, 'chunk_expired' => false, 'key' => '1234' }, payload.to_hash)
25
+ end
26
+ end
@@ -0,0 +1,13 @@
1
+
2
+ require 'test/test_helper'
3
+
4
+ class TestPlugin < ActiveSupport::TestCase
5
+ setup do
6
+ end
7
+
8
+ test "load" do
9
+ assert_raise(NameError) { "MissingMapper".constantize }
10
+ NFAgent::Plugin.load_plugins
11
+ "MyMapper".constantize
12
+ end
13
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 9
8
- - 19
9
- version: 0.9.19
8
+ - 20
9
+ version: 0.9.20
10
10
  platform: ruby
11
11
  authors:
12
12
  - Daniel Draper
@@ -14,8 +14,8 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-01-14 00:00:00 +10:30
18
- default_executable: nfagent
17
+ date: 2011-02-06 00:00:00 +10:30
18
+ default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: svutil
@@ -27,8 +27,8 @@ dependencies:
27
27
  segments:
28
28
  - 0
29
29
  - 0
30
- - 12
31
- version: 0.0.12
30
+ - 13
31
+ version: 0.0.13
32
32
  type: :runtime
33
33
  version_requirements: *id001
34
34
  - !ruby/object:Gem::Dependency
@@ -46,23 +46,35 @@ dependencies:
46
46
  type: :runtime
47
47
  version_requirements: *id002
48
48
  - !ruby/object:Gem::Dependency
49
- name: newgem
49
+ name: squiggle
50
50
  prerelease: false
51
51
  requirement: &id003 !ruby/object:Gem::Requirement
52
52
  requirements:
53
53
  - - ">="
54
54
  - !ruby/object:Gem::Version
55
55
  segments:
56
- - 1
57
- - 5
58
- - 3
59
- version: 1.5.3
60
- type: :development
56
+ - 0
57
+ version: "0"
58
+ type: :runtime
61
59
  version_requirements: *id003
62
60
  - !ruby/object:Gem::Dependency
63
- name: hoe
61
+ name: rubyforge
64
62
  prerelease: false
65
63
  requirement: &id004 !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ segments:
68
+ - 2
69
+ - 0
70
+ - 4
71
+ version: 2.0.4
72
+ type: :development
73
+ version_requirements: *id004
74
+ - !ruby/object:Gem::Dependency
75
+ name: hoe
76
+ prerelease: false
77
+ requirement: &id005 !ruby/object:Gem::Requirement
66
78
  requirements:
67
79
  - - ">="
68
80
  - !ruby/object:Gem::Version
@@ -72,8 +84,8 @@ dependencies:
72
84
  - 0
73
85
  version: 2.6.0
74
86
  type: :development
75
- version_requirements: *id004
76
- description: Logging Agent for NetFox Online
87
+ version_requirements: *id005
88
+ description: FIX (describe your package)
77
89
  email:
78
90
  - daniel@netfox.com
79
91
  executables:
@@ -82,49 +94,64 @@ executables:
82
94
  extensions: []
83
95
 
84
96
  extra_rdoc_files:
85
- - PostInstall.txt
86
97
  - History.txt
87
98
  - Manifest.txt
88
- - README.txt
99
+ - PostInstall.txt
89
100
  - nfagent.init.ubuntu.txt
90
101
  - nfagent.init.redhat.txt
91
102
  files:
103
+ - History.txt
104
+ - Manifest.txt
105
+ - PostInstall.txt
106
+ - README.rdoc
92
107
  - Rakefile
108
+ - script/console
109
+ - script/destroy
110
+ - script/generate
111
+ - test/test_chunk.rb
112
+ - test/test_chunk_handler.rb
113
+ - test/test_client.rb
114
+ - test/test_config.rb
115
+ - test/test_helper.rb
116
+ - test/test_mapper_proxy.rb
117
+ - test/test_nfagent.rb
118
+ - test/test_payload.rb
119
+ - test/test_plugin.rb
120
+ - test/config
121
+ - test/plugins/my_mapper.rb
93
122
  - lib/nfagent.rb
94
- - lib/nfagent/cli.rb
95
123
  - lib/nfagent/base64.rb
96
- - lib/nfagent/encoder.rb
97
- - lib/nfagent/server.rb
98
- - lib/nfagent/chunk_handler.rb
99
- - lib/nfagent/log.rb
100
- - lib/nfagent/info.rb
101
- - lib/nfagent/event.rb
102
- - lib/nfagent/payload.rb
103
- - lib/nfagent/poller.rb
104
124
  - lib/nfagent/chunk.rb
125
+ - lib/nfagent/chunk_handler.rb
126
+ - lib/nfagent/cli.rb
105
127
  - lib/nfagent/client.rb
106
128
  - lib/nfagent/client_response.rb
107
129
  - lib/nfagent/config.rb
130
+ - lib/nfagent/encoder.rb
131
+ - lib/nfagent/event.rb
132
+ - lib/nfagent/info.rb
133
+ - lib/nfagent/log.rb
134
+ - lib/nfagent/mapper_proxy.rb
135
+ - lib/nfagent/payload.rb
136
+ - lib/nfagent/plugin.rb
137
+ - lib/nfagent/poller.rb
138
+ - lib/nfagent/server.rb
139
+ - lib/nfagent/submitter.rb
108
140
  - lib/nfagent/tail.rb
109
141
  - lib/nfagent/tests.rb
110
- - lib/nfagent/submitter.rb
111
142
  - bin/nfagent
112
143
  - bin/squid_log_writer
113
- - PostInstall.txt
114
- - History.txt
115
- - Manifest.txt
116
- - README.txt
117
144
  - nfagent.conf
118
145
  - nfagent.init.ubuntu.txt
119
146
  - nfagent.init.redhat.txt
120
147
  has_rdoc: true
121
- homepage: http://netfox.com
148
+ homepage: http://github.com/#{github_username}/#{project_name}
122
149
  licenses: []
123
150
 
124
151
  post_install_message: PostInstall.txt
125
152
  rdoc_options:
126
153
  - --main
127
- - README.txt
154
+ - README.rdoc
128
155
  require_paths:
129
156
  - lib
130
157
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -147,6 +174,14 @@ rubyforge_project: nfagent
147
174
  rubygems_version: 1.3.6
148
175
  signing_key:
149
176
  specification_version: 3
150
- summary: Logging Agent for NetFox Online
151
- test_files: []
152
-
177
+ summary: FIX (describe your package)
178
+ test_files:
179
+ - test/test_chunk.rb
180
+ - test/test_chunk_handler.rb
181
+ - test/test_client.rb
182
+ - test/test_config.rb
183
+ - test/test_helper.rb
184
+ - test/test_mapper_proxy.rb
185
+ - test/test_nfagent.rb
186
+ - test/test_payload.rb
187
+ - test/test_plugin.rb