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 +1 -1
- data/Manifest.txt +30 -14
- data/PostInstall.txt +6 -0
- data/{README.txt → README.rdoc} +9 -17
- data/Rakefile +18 -21
- data/lib/nfagent.rb +4 -1
- data/lib/nfagent/chunk.rb +26 -16
- data/lib/nfagent/chunk_handler.rb +48 -23
- data/lib/nfagent/client.rb +2 -2
- data/lib/nfagent/config.rb +33 -0
- data/lib/nfagent/mapper_proxy.rb +18 -0
- data/lib/nfagent/payload.rb +4 -2
- data/lib/nfagent/plugin.rb +13 -0
- data/lib/nfagent/server.rb +2 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/test/config +5 -0
- data/test/plugins/my_mapper.rb +17 -0
- data/test/test_chunk.rb +80 -0
- data/test/test_chunk_handler.rb +97 -0
- data/test/test_client.rb +20 -0
- data/test/test_config.rb +40 -0
- data/test/test_helper.rb +6 -0
- data/test/test_mapper_proxy.rb +20 -0
- data/test/test_nfagent.rb +8 -0
- data/test/test_payload.rb +26 -0
- data/test/test_plugin.rb +13 -0
- metadata +71 -36
data/History.txt
CHANGED
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
data/{README.txt → README.rdoc}
RENAMED
@@ -1,40 +1,32 @@
|
|
1
|
-
=
|
1
|
+
= nfagent
|
2
2
|
|
3
|
-
* http://
|
3
|
+
* http://github.com/#{github_username}/#{project_name}
|
4
4
|
|
5
5
|
== DESCRIPTION:
|
6
6
|
|
7
|
-
|
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
|
-
*
|
18
|
-
* SV Util
|
19
|
+
* FIX (list of requirements)
|
19
20
|
|
20
21
|
== INSTALL:
|
21
22
|
|
22
|
-
sudo gem install
|
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)
|
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
|
-
|
2
|
-
|
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
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
-
|
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'
|
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.
|
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
|
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
|
-
|
13
|
+
DEFAULT_MAX_SIZE = 500
|
9
14
|
|
10
|
-
def initialize(max_size =
|
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
|
-
|
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
|
-
|
28
|
+
self.size >= @max_size
|
23
29
|
end
|
24
30
|
|
25
31
|
def expired?
|
26
|
-
(Time.now - @created_at >
|
32
|
+
(Time.now - @created_at > Config.chunk_time_out) && !self.empty?
|
27
33
|
end
|
28
34
|
|
29
|
-
|
30
|
-
def dump
|
35
|
+
def dump(key = nil)
|
31
36
|
Payload.new do |payload|
|
32
|
-
Log.info("Dumping payload from chunk (#{
|
33
|
-
payload.line_count =
|
37
|
+
Log.info("Dumping payload from chunk (#{self.size} lines)")
|
38
|
+
payload.line_count = self.size
|
34
39
|
payload.chunk_expired = expired?
|
35
|
-
payload.
|
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
|
41
|
-
|
42
|
-
|
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
|
-
|
5
|
-
|
6
|
-
|
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
-
|
33
|
-
|
34
|
-
|
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
|
data/lib/nfagent/client.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module NFAgent
|
2
2
|
class Client
|
3
|
-
|
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(
|
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
|
data/lib/nfagent/config.rb
CHANGED
@@ -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
|
data/lib/nfagent/payload.rb
CHANGED
@@ -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)
|
data/lib/nfagent/server.rb
CHANGED
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,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
|
data/test/test_chunk.rb
ADDED
@@ -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
|
data/test/test_client.rb
ADDED
@@ -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
|
data/test/test_config.rb
ADDED
@@ -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
|
data/test/test_helper.rb
ADDED
@@ -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,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
|
data/test/test_plugin.rb
ADDED
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 9
|
8
|
-
-
|
9
|
-
version: 0.9.
|
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-
|
18
|
-
default_executable:
|
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
|
-
-
|
31
|
-
version: 0.0.
|
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:
|
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
|
-
-
|
57
|
-
|
58
|
-
|
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:
|
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: *
|
76
|
-
description:
|
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
|
-
-
|
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://
|
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.
|
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:
|
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
|