arii 1.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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +17 -0
- data/LICENSE +22 -0
- data/README.md +33 -0
- data/Rakefile +12 -0
- data/arii.gemspec +26 -0
- data/lib/arii/agent.rb +119 -0
- data/lib/arii/cashier.rb +28 -0
- data/lib/arii/client.rb +53 -0
- data/lib/arii/csvdetector.rb +63 -0
- data/lib/arii/csvseedreader.rb +47 -0
- data/lib/arii/detector.rb +113 -0
- data/lib/arii/helper.rb +152 -0
- data/lib/arii/jsondetector.rb +67 -0
- data/lib/arii/jsonseedreader.rb +52 -0
- data/lib/arii/seedreader.rb +21 -0
- data/lib/arii/sqldetector.rb +57 -0
- data/lib/arii/sqlseedreader.rb +46 -0
- data/lib/arii/version.rb +3 -0
- data/lib/arii/xmldetector.rb +62 -0
- data/lib/arii/xmlseedreader.rb +52 -0
- data/lib/arii.rb +43 -0
- data/test/lib/i2x/version_test.rb +9 -0
- data/test/test_helper.rb +4 -0
- metadata +142 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: fa7fad175dce5a6ceb4352b89870f1c76ba33278
|
4
|
+
data.tar.gz: 90107e53cb008572777cbb78b6f7be7ae67cda87
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 02b6d28829dd27c53e133a0397e956f80e5b4b8c0e279169f52af8187ec35d0f9e455c305944590ffbb8c3959366a043cfcd38eab51bccc6bd77d29cc6015265
|
7
|
+
data.tar.gz: 9c6d6e4d09ff0dbba96cfa314cf6476816d95588e4660d66453d44586734133d3e4fb967a77a6b87a665d73efa78ab320fec2071b2cd07450ca7eaeca20d0c48
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Pedro Lopes
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# ARiiP gem
|
2
|
+
|
3
|
+
Ruby `gem` for distributed client agents. This enables launching custom **ARiiP** agents.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'arii'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install arii
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
- Check **ARiiP**'s [client](http://github.com/pdrlps/arii-client)
|
22
|
+
|
23
|
+
## Changelog
|
24
|
+
|
25
|
+
- 2015-01-14: Reload as arii-gem
|
26
|
+
|
27
|
+
## Contributing
|
28
|
+
|
29
|
+
1. Fork it ( http://github.com/pdrlps/arii-gem/fork )
|
30
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
31
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
32
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
33
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/arii.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'arii/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "arii"
|
8
|
+
spec.version = ARII::VERSION
|
9
|
+
spec.authors = ["Pedro Lopes"]
|
10
|
+
spec.email = ["hello@pedrolopes.net"]
|
11
|
+
spec.summary = %q{arii client library for distributed agents.}
|
12
|
+
spec.description = %q{ARiiP: integrate everything. Automated real-time integration & interoperability platform.}
|
13
|
+
spec.homepage = "http://ariip.com/"
|
14
|
+
spec.license = "MIT"
|
15
|
+
spec.files = `git ls-files`.split($/)
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
21
|
+
spec.add_development_dependency "rake", '~> 0'
|
22
|
+
|
23
|
+
spec.add_runtime_dependency 'rest-client', '~> 0'
|
24
|
+
spec.add_runtime_dependency 'nokogiri'
|
25
|
+
spec.add_runtime_dependency 'jsonpath', '~> 0'
|
26
|
+
end
|
data/lib/arii/agent.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'rest_client'
|
2
|
+
|
3
|
+
module ARII
|
4
|
+
class Agent
|
5
|
+
attr_accessor :content, :identifier, :publisher, :payload, :templates, :seeds, :cache, :selectors
|
6
|
+
|
7
|
+
def initialize agent
|
8
|
+
begin
|
9
|
+
@identifier = agent[:identifier]
|
10
|
+
@publisher = agent[:publisher]
|
11
|
+
@payload = agent[:payload]
|
12
|
+
@cache = agent[:payload][:cache]
|
13
|
+
@seeds = agent[:seeds]
|
14
|
+
@selectors = agent[:payload][:selectors]
|
15
|
+
ARII::Config.log.debug(self.class.name) {"Agent #{@identifier} initialized"}
|
16
|
+
rescue Exception => e
|
17
|
+
ARII::Config.log.error(self.class.name) {"Unable to initialize agent. #{e}"}
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
##
|
24
|
+
# => Perform the actual agent monitoring tasks.
|
25
|
+
#
|
26
|
+
def execute
|
27
|
+
@checkup = {}
|
28
|
+
|
29
|
+
case @publisher
|
30
|
+
when 'sql'
|
31
|
+
begin
|
32
|
+
@d = ARII::SQLDetector.new(self)
|
33
|
+
rescue Exception => e
|
34
|
+
@response = {:status => 400, :error => e}
|
35
|
+
ARII::Config.log.error(self.class.name) {"#{e}"}
|
36
|
+
end
|
37
|
+
when 'csv'
|
38
|
+
begin
|
39
|
+
@d = ARII::CSVDetector.new(self)
|
40
|
+
rescue Exception => e
|
41
|
+
@response = {:status => 400, :error => e}
|
42
|
+
ARII::Config.log.error(self.class.name) {"#{e}"}
|
43
|
+
end
|
44
|
+
when 'xml'
|
45
|
+
begin
|
46
|
+
@d = ARII::XMLDetector.new(self)
|
47
|
+
rescue Exception => e
|
48
|
+
@response = {:status => 400, :error => e}
|
49
|
+
ARII::Config.log.error(self.class.name) {"#{e}"}
|
50
|
+
end
|
51
|
+
when 'json'
|
52
|
+
begin
|
53
|
+
@d = ARII::JSONDetector.new(self)
|
54
|
+
rescue Exception => e
|
55
|
+
@response = {:status => 400, :error => e}
|
56
|
+
ARII::Config.log.error(self.class.name) {"#{e}"}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
# Start checkup
|
62
|
+
begin
|
63
|
+
unless content.nil? then
|
64
|
+
@d.content = content
|
65
|
+
end
|
66
|
+
@checkup = @d.checkup
|
67
|
+
rescue Exception => e
|
68
|
+
ARII::Config.log.error(self.class.name) {"Checkup error: #{e}"}
|
69
|
+
end
|
70
|
+
|
71
|
+
# Start detection
|
72
|
+
begin
|
73
|
+
@d.objects.each do |object|
|
74
|
+
@d.detect object
|
75
|
+
end
|
76
|
+
|
77
|
+
@checkup[:templates] = @d.templates.uniq
|
78
|
+
rescue Exception => e
|
79
|
+
ARII::Config.log.error(self.class.name) {"Detection error: #{e}"}
|
80
|
+
end
|
81
|
+
|
82
|
+
begin
|
83
|
+
if @checkup[:status] == 100 then
|
84
|
+
process @checkup
|
85
|
+
end
|
86
|
+
rescue Exception => e
|
87
|
+
ARII::Config.log.error(self.class.name) {"Process error: #{e}"}
|
88
|
+
end
|
89
|
+
response = {:status => @checkup[:status], :message => "[ARII][Checkup][execute] All OK."}
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
##
|
95
|
+
# => Process agent checks.
|
96
|
+
#
|
97
|
+
def process checkup
|
98
|
+
begin
|
99
|
+
checkup[:templates].each do |template|
|
100
|
+
ARII::Config.log.info(self.class.name) {"Delivering to #{template} template."}
|
101
|
+
checkup[:payload].each do |payload|
|
102
|
+
ARII::Config.log.debug(self.class.name) {"Processing #{payload}."}
|
103
|
+
response = RestClient.post "#{ARII::Config.host}postman/deliver/#{template}.js", payload
|
104
|
+
case response.code
|
105
|
+
when 200
|
106
|
+
|
107
|
+
else
|
108
|
+
ARII::Config.log.warn(self.class.name) {"unable to deliver \"#{payload}\" to \"#{template}\""}
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
rescue Exception => e
|
113
|
+
ARII::Config.log.error(self.class.name) {"Processing error: #{e}"}
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
data/lib/arii/cashier.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rest_client'
|
2
|
+
|
3
|
+
module ARII
|
4
|
+
class Cashier
|
5
|
+
public
|
6
|
+
|
7
|
+
##
|
8
|
+
# = Verify
|
9
|
+
# => Verify if items have already been seen in the past (on the cache).
|
10
|
+
#
|
11
|
+
# == Params
|
12
|
+
# - *cache*: the key identifier to be verified
|
13
|
+
# - *payload*: the value for matching/verification
|
14
|
+
# - *agent*: the agent performing the verification
|
15
|
+
# - *seed*: seed data (if available)
|
16
|
+
#
|
17
|
+
def self.verify cache, agent, payload, seed
|
18
|
+
ARII::Config.log.info(self.class.name) {"Verifying\n\taccess token: #{ARII::Config.access_token}\n\thost: #{ARII::Config.host}\n\tcache: #{cache}\n\tagent: #{agent}\n\tpayload: #{payload}\tseed: #{seed}"}
|
19
|
+
begin
|
20
|
+
response = RestClient.post "#{ARII::Config.host}fluxcapacitor/verify.json", {:access_token => ARII::Config.access_token, :agent => agent[:identifier], :cache => cache, :payload => payload, :seed => seed}
|
21
|
+
rescue Exception => e
|
22
|
+
ARII::Config.log.error(self.class.name) {"#{e}"}
|
23
|
+
response = {:status => 400, :error => e}
|
24
|
+
end
|
25
|
+
response
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/arii/client.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'rest_client'
|
2
|
+
|
3
|
+
module ARII
|
4
|
+
class Client
|
5
|
+
|
6
|
+
##
|
7
|
+
# => Load configuration properties from client/script code
|
8
|
+
#
|
9
|
+
def initialize config, log
|
10
|
+
begin
|
11
|
+
@config = config
|
12
|
+
ARII::Config.set_access_token config[:server][:api_key]
|
13
|
+
ARII::Config.set_host config[:server][:host]
|
14
|
+
ARII::Config.set_log log
|
15
|
+
|
16
|
+
ARII::Config.log.info(self.class.name) {'Configuration loaded successfully.'}
|
17
|
+
rescue Exception => e
|
18
|
+
ARII::Config.log.error(self.class.name) {"Failed to load configuration: #{e}"}
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# => Validate API key.
|
25
|
+
#
|
26
|
+
def validate
|
27
|
+
begin
|
28
|
+
ARII::Config.log.info(self.class.name) {'Launching validation.'}
|
29
|
+
|
30
|
+
out = RestClient.post "#{ARII::Config.host}fluxcapacitor/validate_key.json", {:access_token => ARII::Config.access_token}
|
31
|
+
response = {:status => 100, :response => out.to_str}
|
32
|
+
rescue Exception => e
|
33
|
+
ARII::Config.log.error(self.class.name) {"Failed validation: #{e}"}
|
34
|
+
end
|
35
|
+
response
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# => Start processing agents from configuration properties.
|
40
|
+
#
|
41
|
+
def process
|
42
|
+
ARII::Config.log.info(self.class.name) {'Starting agent processing.'}
|
43
|
+
begin
|
44
|
+
@config[:agents].each do |agent|
|
45
|
+
a = ARII::Agent.new agent
|
46
|
+
a.execute
|
47
|
+
end
|
48
|
+
rescue Exception => e
|
49
|
+
ARII::Config.log.error(self.class.name) {"Failed agent processing: #{e}"}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'csv'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
module ARII
|
5
|
+
|
6
|
+
##
|
7
|
+
# = CSVDetector
|
8
|
+
#
|
9
|
+
# Detect changes in CSV files (using column numbers).
|
10
|
+
#
|
11
|
+
class CSVDetector < Detector
|
12
|
+
|
13
|
+
public
|
14
|
+
##
|
15
|
+
# == Detect the changes
|
16
|
+
#
|
17
|
+
def detect object
|
18
|
+
|
19
|
+
ARII::Config.log.debug(self.class.name) {"Monitoring #{object[:uri]}"}
|
20
|
+
CSV.new(open(object[:uri]), :headers => :first_row).each do |row|
|
21
|
+
begin
|
22
|
+
unless object[:cache].nil? then
|
23
|
+
@response = Cashier.verify row[object[:cache].to_i], object, row, object[:seed]
|
24
|
+
else
|
25
|
+
@response = Cashier.verify row[0], object, row, object[:seed]
|
26
|
+
end
|
27
|
+
rescue Exception => e
|
28
|
+
ARII::Config.log.error(self.class.name) {"Loading error: #{e}"}
|
29
|
+
end
|
30
|
+
|
31
|
+
begin
|
32
|
+
|
33
|
+
# Process ARIIcache response
|
34
|
+
@cache = JSON.parse(@response, {:symbolize_names => true})
|
35
|
+
unless @cache[:templates].nil? then
|
36
|
+
@cache[:templates].each do |t|
|
37
|
+
@templates.push t
|
38
|
+
end
|
39
|
+
end
|
40
|
+
# The actual processing
|
41
|
+
#
|
42
|
+
if @cache[:cache][:status] == 100 then
|
43
|
+
ARII::Config.log.info(self.class.name) {"Not on cache, generating payload"}
|
44
|
+
|
45
|
+
payload = Hash.new
|
46
|
+
|
47
|
+
object[:selectors].each do |selector|
|
48
|
+
selector.each do |k,v|
|
49
|
+
payload[k] = row[v.to_i]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
# add payload object to payloads list
|
53
|
+
@payloads.push payload
|
54
|
+
end
|
55
|
+
|
56
|
+
rescue Exception => e
|
57
|
+
ARII::Config.log.error(self.class.name) {"Processing error: #{e}"}
|
58
|
+
end
|
59
|
+
@cache[:templates]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'csv'
|
2
|
+
|
3
|
+
module ARII
|
4
|
+
|
5
|
+
# = CSVSeedReader
|
6
|
+
#
|
7
|
+
# Load content from CSV seed.
|
8
|
+
#
|
9
|
+
class CSVSeedReader < SeedReader
|
10
|
+
##
|
11
|
+
# == Read
|
12
|
+
#
|
13
|
+
# => Load the seed data into the @objects array for processing.
|
14
|
+
#
|
15
|
+
def read
|
16
|
+
begin
|
17
|
+
CSV.new(open(@seed[:payload][:uri]), :headers => :first_row).each do |row|
|
18
|
+
begin
|
19
|
+
object = @help.deep_copy @agent[:payload]
|
20
|
+
object.each_pair do |key,value|
|
21
|
+
variables = @help.identify_variables(object[key])
|
22
|
+
variables.each do |v|
|
23
|
+
object[key].gsub!("%{#{v}}", row[@seed[:payload][:selectors][v].to_i])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
unless @seed[:payload][:cache].nil? then
|
28
|
+
object[:seed] = row[@seed[:payload][:cache].to_i]
|
29
|
+
else
|
30
|
+
object[:seed] = row[0]
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
object[:identifier] = @agent.identifier
|
35
|
+
@objects.push object
|
36
|
+
rescue Exception => e
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
rescue Exception => e
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
@objects
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
#require 'seedreader'
|
2
|
+
#require 'csvseedreader'
|
3
|
+
#require 'sqlseedreader'
|
4
|
+
#require 'xmlseedreader'
|
5
|
+
#require 'jsonseedreader'
|
6
|
+
|
7
|
+
|
8
|
+
module ARII
|
9
|
+
|
10
|
+
##
|
11
|
+
# = Detector
|
12
|
+
#
|
13
|
+
# Main change detection class, to be inherited by SQL, CSV, JSON and XML detectors (and others to come).
|
14
|
+
#
|
15
|
+
class Detector
|
16
|
+
attr_accessor :identifier, :agent, :objects, :payloads, :content, :templates
|
17
|
+
|
18
|
+
def initialize agent
|
19
|
+
begin
|
20
|
+
@agent = agent
|
21
|
+
@payloads = Array.new
|
22
|
+
@objects = Array.new
|
23
|
+
@help = ARII::Helper.new
|
24
|
+
ARII::Config.log.info(self.class.name) {"Started new #{agent.identifier} detector"}
|
25
|
+
rescue Exception => e
|
26
|
+
ARII::Config.log.error(self.class.name) {"#{e}"}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
##
|
32
|
+
# == Start original source detection process
|
33
|
+
#
|
34
|
+
def checkup
|
35
|
+
|
36
|
+
begin
|
37
|
+
|
38
|
+
|
39
|
+
##
|
40
|
+
# => Process seed data, if available.
|
41
|
+
#
|
42
|
+
unless @agent.seeds.nil? then
|
43
|
+
@agent.seeds.each do |seed|
|
44
|
+
case seed[:publisher]
|
45
|
+
when 'csv'
|
46
|
+
begin
|
47
|
+
@sr = ARII::CSVSeedReader.new(@agent, seed)
|
48
|
+
rescue Exception => e
|
49
|
+
ARII::Config.log.error(self.class.name) {"#{e}"}
|
50
|
+
end
|
51
|
+
when 'sql'
|
52
|
+
begin
|
53
|
+
@sr = ARII::SQLSeedReader.new(@agent, seed)
|
54
|
+
rescue Exception => e
|
55
|
+
ARII::Config.log.error(self.class.name) {"#{e}"}
|
56
|
+
end
|
57
|
+
when 'xml'
|
58
|
+
begin
|
59
|
+
@sr = ARII::XMLSeedReader.new(@agent, seed)
|
60
|
+
rescue Exception => e
|
61
|
+
ARII::Config.log.error(self.class.name) {"#{e}"}
|
62
|
+
end
|
63
|
+
when 'json'
|
64
|
+
begin
|
65
|
+
@sr = ARII::JSONSeedReader.new(@agent, seed)
|
66
|
+
rescue Exception => e
|
67
|
+
ARII::Config.log.error(self.class.name) {"#{e}"}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
begin
|
71
|
+
@reads = @sr.read
|
72
|
+
@reads.each do |read|
|
73
|
+
@objects.push read
|
74
|
+
end
|
75
|
+
rescue Exception => e
|
76
|
+
ARII::Config.log.error(self.class.name) {"#{e}"}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
else
|
81
|
+
##
|
82
|
+
# no seeds, simply copy agent data
|
83
|
+
object = @help.deep_copy @agent.payload
|
84
|
+
object[:identifier] = @agent.identifier
|
85
|
+
object[:cache] = @agent.cache
|
86
|
+
object[:seed] = object[:identifier]
|
87
|
+
object[:selectors] = @agent.selectors
|
88
|
+
unless self.content.nil? then
|
89
|
+
object[:content] = self.content
|
90
|
+
end
|
91
|
+
@objects.push object
|
92
|
+
end
|
93
|
+
rescue Exception => e
|
94
|
+
@response = {:status => 404, :message => "[ARII][Detector] failed to load doc, #{e}"}
|
95
|
+
ARII::Config.log.error(self.class.name) {"#{e}"}
|
96
|
+
end
|
97
|
+
|
98
|
+
begin
|
99
|
+
# increase detected events count
|
100
|
+
|
101
|
+
|
102
|
+
@templates = Array.new
|
103
|
+
@response = { :payload => @payloads, :templates => @templates, :status => 100}
|
104
|
+
rescue Exception => e
|
105
|
+
@response = {:status => 404, :message => "[ARII][Detector] failed to process queries, #{e}"}
|
106
|
+
ARII::Config.log.error(self.class.name) {"#{e}"}
|
107
|
+
end
|
108
|
+
@response
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
data/lib/arii/helper.rb
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
|
2
|
+
module ARII
|
3
|
+
|
4
|
+
##
|
5
|
+
# = Helper Class
|
6
|
+
# => Miscellaneous helper methods and utils to deal with data.
|
7
|
+
#
|
8
|
+
class Helper
|
9
|
+
attr_accessor :replacements
|
10
|
+
@replacements
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
# load each helper function into a map for replacement in the delivery
|
14
|
+
@replacements = [ ["%{ARII.date}", self.date], ["%{ARII.datetime}", self.datetime], ["%{ARII.hostname}", self.hostname]]
|
15
|
+
end
|
16
|
+
|
17
|
+
public
|
18
|
+
def hostname
|
19
|
+
ENV["APP_HOST"]
|
20
|
+
end
|
21
|
+
|
22
|
+
def datetime
|
23
|
+
Time.now.to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
def date
|
27
|
+
Time.now.strftime("%Y-%m-%d").to_s
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# == Identify Variables
|
32
|
+
# => Identifies variables on string set, generates array with all scanned variables for processing.
|
33
|
+
# => Variables are enclosed in %{variable} string.
|
34
|
+
#
|
35
|
+
# * +text+ - string to be scanned
|
36
|
+
#
|
37
|
+
def identify_variables text
|
38
|
+
begin
|
39
|
+
results = Array.new
|
40
|
+
text.scan(/%{(.*?)}/).each do |m|
|
41
|
+
results.push m[0]
|
42
|
+
end
|
43
|
+
rescue Exception => e
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
results
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# == Validate payload
|
52
|
+
# => Validates content payload.
|
53
|
+
#
|
54
|
+
# + *publisher* - for publisher-specific validations
|
55
|
+
# + *payload* - content for validation
|
56
|
+
#
|
57
|
+
def self.validate_payload publisher, payload
|
58
|
+
@database_servers = ["mysql","sqlite","postgresql"]
|
59
|
+
valid = true
|
60
|
+
|
61
|
+
begin
|
62
|
+
case publisher
|
63
|
+
when 'csv', 'xml', 'json', 'file', 'js'
|
64
|
+
# file content URI is mandatory
|
65
|
+
if payload[:uri].nil? then
|
66
|
+
valid = false
|
67
|
+
end
|
68
|
+
when 'sql'
|
69
|
+
|
70
|
+
# check if database server is available
|
71
|
+
unless database_servers.include? payload[:server] then
|
72
|
+
valid = false
|
73
|
+
end
|
74
|
+
|
75
|
+
# database username is mandatory
|
76
|
+
if payload[:username].nil? then
|
77
|
+
valid = false
|
78
|
+
end
|
79
|
+
|
80
|
+
# database user password is mandatory
|
81
|
+
if payload[:password].nil? then
|
82
|
+
valid = false
|
83
|
+
end
|
84
|
+
|
85
|
+
# database name is mandatory
|
86
|
+
if payload[:database].nil? then
|
87
|
+
valid = false
|
88
|
+
end
|
89
|
+
|
90
|
+
# database query is mandatory
|
91
|
+
if payload[:query].nil? then
|
92
|
+
valid = false
|
93
|
+
end
|
94
|
+
end
|
95
|
+
rescue Exception => e
|
96
|
+
|
97
|
+
end
|
98
|
+
valid
|
99
|
+
end
|
100
|
+
|
101
|
+
##
|
102
|
+
# == Validate Seed
|
103
|
+
# => Validates Seed-specific properties
|
104
|
+
#
|
105
|
+
# + *publisher* - for publisher-specific validations
|
106
|
+
# + *seed* - the seed hash
|
107
|
+
#
|
108
|
+
def self.validate_seed publisher, seed
|
109
|
+
begin
|
110
|
+
valid = self.validate_payload publisher, seed
|
111
|
+
if valid then
|
112
|
+
# seed must have selectors
|
113
|
+
if seed[:selectors].nil? then
|
114
|
+
valid = false
|
115
|
+
end
|
116
|
+
else
|
117
|
+
valid = false
|
118
|
+
end
|
119
|
+
rescue Exception => e
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
valid
|
124
|
+
end
|
125
|
+
|
126
|
+
##
|
127
|
+
# == Validate Agent
|
128
|
+
# => Validates Agent-specific properties
|
129
|
+
#
|
130
|
+
# + *agent* - the agent for validation
|
131
|
+
#
|
132
|
+
def self.validate_agent
|
133
|
+
begin
|
134
|
+
valid = self.validate_seed(agent[:publisher], agent[:payload]) && self.validate_payload(agent[:publisher], agent[:payload])
|
135
|
+
rescue Exception => e
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
valid
|
140
|
+
end
|
141
|
+
|
142
|
+
##
|
143
|
+
# == Copy Object/Hash/Array...
|
144
|
+
# => Copies any object into new object (overcome references).
|
145
|
+
#
|
146
|
+
# + *o* - the object being copied
|
147
|
+
#
|
148
|
+
def deep_copy object
|
149
|
+
Marshal.load(Marshal.dump(object))
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'jsonpath'
|
3
|
+
require 'rest_client'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
module ARII
|
7
|
+
|
8
|
+
# = JSONDetector
|
9
|
+
#
|
10
|
+
# Detect changes in JSON content files (uses JSONPath).
|
11
|
+
#
|
12
|
+
class JSONDetector < Detector
|
13
|
+
|
14
|
+
public
|
15
|
+
|
16
|
+
##
|
17
|
+
# == Detect the changes
|
18
|
+
#
|
19
|
+
def detect object
|
20
|
+
ARII::Config.log.info(self.class.name) {"Monitoring #{object[:uri]}"} unless object[:uri].nil?
|
21
|
+
|
22
|
+
begin
|
23
|
+
if object[:uri] == '' then
|
24
|
+
@doc = object[:content]
|
25
|
+
else
|
26
|
+
url = RestClient.get object[:uri]
|
27
|
+
@doc = url.to_str
|
28
|
+
end
|
29
|
+
JsonPath.on(@doc,object[:query]).each do |element|
|
30
|
+
JsonPath.on(element, object[:cache]).each do |c|
|
31
|
+
@response = Cashier.verify c, object, c, object[:seed]
|
32
|
+
end
|
33
|
+
|
34
|
+
# Process ARII cache response
|
35
|
+
@cache = JSON.parse(@response, {:symbolize_names => true})
|
36
|
+
unless @cache[:templates].nil? then
|
37
|
+
@cache[:templates].each do |t|
|
38
|
+
@templates.push t
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# If not on cache, add to payload for processing
|
44
|
+
#
|
45
|
+
if @cache[:status] == 100 then
|
46
|
+
ARII::Config.log.info(self.class.name) {"Not on cache, generating payload"}
|
47
|
+
# add row data to payload from selectors (key => key, value => column name)
|
48
|
+
payload = Hash.new
|
49
|
+
object[:selectors].each do |selector|
|
50
|
+
selector.each do |k,v|
|
51
|
+
JsonPath.on(element, v).each do |el|
|
52
|
+
payload[k] = el
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
# add payload object to payloads list
|
57
|
+
@payloads.push payload
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
rescue Exception => e
|
62
|
+
ARII::Config.log.error(self.class.name) {"Loading error: #{e}"}
|
63
|
+
end
|
64
|
+
@cache[:templates]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module ARII
|
4
|
+
|
5
|
+
# = JSONSeedReader
|
6
|
+
#
|
7
|
+
# Load content from JSON seed.
|
8
|
+
#
|
9
|
+
class JSONSeedReader < SeedReader
|
10
|
+
##
|
11
|
+
# == Read
|
12
|
+
#
|
13
|
+
# => Load the seed data into the @objects array for processing.
|
14
|
+
#
|
15
|
+
def read
|
16
|
+
begin
|
17
|
+
url = RestClient.get @seed[:payload][:uri]
|
18
|
+
@doc = url.to_str
|
19
|
+
JsonPath.on(@doc,@seed[:payload][:query]).each do |element|
|
20
|
+
|
21
|
+
begin
|
22
|
+
object = @help.deep_copy @agent[:payload]
|
23
|
+
object.each_pair do |key,value|
|
24
|
+
variables = @help.identify_variables(object[key])
|
25
|
+
variables.each do |v|
|
26
|
+
|
27
|
+
JsonPath.on(element, @seed[:payload][:selectors][v]).each do |el|
|
28
|
+
|
29
|
+
object[key].gsub!("%{#{v}}", el.to_s)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
JsonPath.on(element,@seed[:payload][:cache]).each do |el|
|
35
|
+
object[:seed] = el
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
object[:identifier] = @agent.identifier
|
40
|
+
@objects.push object
|
41
|
+
rescue Exception => e
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
rescue Exception => e
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
@objects
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
#require 'helper'
|
2
|
+
|
3
|
+
module ARII
|
4
|
+
|
5
|
+
##
|
6
|
+
# = Seed Reader
|
7
|
+
#
|
8
|
+
# Main seed reading class, passing data for seeds to agent, to be inherited by SQL, File and URL templates
|
9
|
+
#
|
10
|
+
class SeedReader
|
11
|
+
attr_accessor :seed, :objects, :agent
|
12
|
+
|
13
|
+
def initialize agent, seed
|
14
|
+
@agent = agent
|
15
|
+
@help = ARII::Helper.new
|
16
|
+
@seed = seed
|
17
|
+
@objects = Array.new
|
18
|
+
puts "\t\tSeed: #{@seed[:identifier]}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
#require 'helper'
|
2
|
+
require 'mysql2'
|
3
|
+
|
4
|
+
module ARII
|
5
|
+
|
6
|
+
##
|
7
|
+
# = SQLDetector
|
8
|
+
#
|
9
|
+
# Detec changes in SQL databases. MySQL support only.
|
10
|
+
#
|
11
|
+
class SQLDetector < Detector
|
12
|
+
|
13
|
+
public
|
14
|
+
##
|
15
|
+
# == Detect the changes
|
16
|
+
#
|
17
|
+
def detect object
|
18
|
+
ARII::Config.log.debug(self.class.name) {"Monitoring #{object[:host]}"}
|
19
|
+
begin
|
20
|
+
@client = Mysql2::Client.new(:host => object[:host], :username => object[:username] , :password => object[:password] , :database => object[:database])
|
21
|
+
@client.query(@agent[:payload][:query]).each(:symbolize_keys => false) do |row|
|
22
|
+
unless object[:cache].nil? then
|
23
|
+
@response = Cashier.verify row[object[:cache]], object, row, object[:seed]
|
24
|
+
else
|
25
|
+
@response = Cashier.verify row["id"], object, row, object[:seed]
|
26
|
+
end
|
27
|
+
|
28
|
+
# Process ARII cache response
|
29
|
+
@cache = JSON.parse(@response, {:symbolize_names => true})
|
30
|
+
unless @cache[:templates].nil? then
|
31
|
+
@cache[:templates].each do |t|
|
32
|
+
@templates.push t
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# The actual processing
|
37
|
+
#
|
38
|
+
if @cache[:status] == 100 then
|
39
|
+
ARII::Config.log.info(self.class.name) {"Not on cache, generating payload"}
|
40
|
+
# add row data to payload from selectors (key => key, value => column name)
|
41
|
+
payload = Hash.new
|
42
|
+
object[:selectors].each do |selector|
|
43
|
+
selector.each do |k,v|
|
44
|
+
payload[k] = row[v]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
# add payload object to payloads list
|
48
|
+
@payloads.push payload
|
49
|
+
end
|
50
|
+
end
|
51
|
+
rescue Exception => e
|
52
|
+
ARII::Config.log.error(self.class.name) {"Processing error: #{e}"}
|
53
|
+
end
|
54
|
+
@cache[:templates]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'mysql2'
|
2
|
+
|
3
|
+
module Services
|
4
|
+
|
5
|
+
# = SQLSeedReader
|
6
|
+
#
|
7
|
+
# Load content from SQL seed.
|
8
|
+
#
|
9
|
+
class SQLSeedReader < SeedReader
|
10
|
+
##
|
11
|
+
# == Read
|
12
|
+
#
|
13
|
+
# => Load the seed data into the @objects array for processing.
|
14
|
+
#
|
15
|
+
def read
|
16
|
+
begin
|
17
|
+
@client = Mysql2::Client.new(:host => @seed[:payload][:host], :username => @seed[:payload][:username] , :password => @seed[:payload][:password] , :database => @seed[:payload][:database])
|
18
|
+
@client.query(@seed[:payload][:query], :cast => false).each(:symbolize_keys => false) do |row|
|
19
|
+
begin
|
20
|
+
object = @help.deep_copy @agent[:payload]
|
21
|
+
object.each_pair do |key,value|
|
22
|
+
variables = @help.identify_variables(object[key])
|
23
|
+
variables.each do |v|
|
24
|
+
object[key].gsub!("%{#{v}}", row[@seed[:payload][:selectors][v]].to_str)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
unless @seed[:payload][:cache].nil? then
|
29
|
+
object[:seed] = row[@seed[:payload][:cache]]
|
30
|
+
else
|
31
|
+
object[:seed] = row["id"]
|
32
|
+
end
|
33
|
+
object[:identifier] = @agent.identifier
|
34
|
+
@objects.push object
|
35
|
+
rescue Exception => e
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
rescue Exception => e
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
@objects
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/arii/version.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
|
3
|
+
module ARII
|
4
|
+
|
5
|
+
# = XMLDetector
|
6
|
+
#
|
7
|
+
# Detect changes in XML files (uses XPath).
|
8
|
+
#
|
9
|
+
class XMLDetector < Detector
|
10
|
+
|
11
|
+
public
|
12
|
+
##
|
13
|
+
# == Detect the changes
|
14
|
+
#
|
15
|
+
def detect object
|
16
|
+
ARII::Config.log.info(self.class.name) {"Monitoring #{object[:uri]}"} unless object[:uri].nil?
|
17
|
+
begin
|
18
|
+
if object[:uri] == '' then
|
19
|
+
@doc = Nokogiri::XML(object[:content])
|
20
|
+
else
|
21
|
+
@doc = Nokogiri::XML(open(object[:uri]))
|
22
|
+
end
|
23
|
+
@doc.remove_namespaces!
|
24
|
+
@doc.xpath(object[:query]).each do |element|
|
25
|
+
element.xpath(object[:cache]).each do |c|
|
26
|
+
@response = Cashier.verify c.content, object, c.content, object[:seed]
|
27
|
+
end
|
28
|
+
|
29
|
+
# Process ARII cache response
|
30
|
+
@cache = JSON.parse(@response, {:symbolize_names => true})
|
31
|
+
unless @cache[:templates].nil? then
|
32
|
+
@cache[:templates].each do |t|
|
33
|
+
@templates.push t
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# If not on cache, add to payload for processing
|
39
|
+
#
|
40
|
+
if @cache[:status] == 100 then
|
41
|
+
ARII::Config.log.info(self.class.name) {"Not on cache, generating payload"}
|
42
|
+
# add row data to payload from selectors (key => key, value => column name)
|
43
|
+
payload = Hash.new
|
44
|
+
object[:selectors].each do |selector|
|
45
|
+
|
46
|
+
selector.each do |k,v|
|
47
|
+
element.xpath(v).each do |el|
|
48
|
+
payload[k] = el.content
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
# add payload object to payloads list
|
53
|
+
@payloads.push payload
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
rescue Exception => e
|
59
|
+
ARII::Config.log.error(self.class.name) {"Processing error: #{e}"}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module ARII
|
2
|
+
|
3
|
+
# = XMLSeedReader
|
4
|
+
#
|
5
|
+
# Load content from XML seed.
|
6
|
+
#
|
7
|
+
class XMLSeedReader < SeedReader
|
8
|
+
##
|
9
|
+
# == Read
|
10
|
+
#
|
11
|
+
# => Load the seed data into the @objects array for processing.
|
12
|
+
#
|
13
|
+
def read
|
14
|
+
begin
|
15
|
+
@doc = Nokogiri::XML(open(@seed[:payload][:uri]))
|
16
|
+
@doc.remove_namespaces!
|
17
|
+
@doc.xpath(@seed[:payload][:query]).each do |element|
|
18
|
+
begin
|
19
|
+
object = @help.deep_copy @agent[:payload]
|
20
|
+
object.each_pair do |key,value|
|
21
|
+
variables = @help.identify_variables(object[key])
|
22
|
+
variables.each do |v|
|
23
|
+
element.xpath(@seed[:payload][:selectors][v]).each do |el|
|
24
|
+
object[key].gsub!("%{#{v}}", el.content)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
unless @seed[:payload][:cache].nil? then
|
30
|
+
element.xpath(@seed[:payload][:cache]).each do |el|
|
31
|
+
object[:seed] = el.content
|
32
|
+
end
|
33
|
+
else
|
34
|
+
element.xpath('id').each do |el|
|
35
|
+
object[:seed] = el.content
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
object[:identifier] = @agent.identifier
|
40
|
+
@objects.push object
|
41
|
+
rescue Exception => e
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
rescue Exception => e
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
@objects
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/arii.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'arii/cashier'
|
3
|
+
require 'arii/helper'
|
4
|
+
require 'arii/detector'
|
5
|
+
require 'arii/csvdetector'
|
6
|
+
require 'arii/jsondetector'
|
7
|
+
require 'arii/sqldetector'
|
8
|
+
require 'arii/xmldetector'
|
9
|
+
require 'arii/agent'
|
10
|
+
require 'arii/version'
|
11
|
+
require 'arii/client'
|
12
|
+
|
13
|
+
module ARII
|
14
|
+
class Config
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
def self.set_log log
|
19
|
+
@@log = log
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.set_host host
|
23
|
+
host << '/' unless host.end_with?('/')
|
24
|
+
@@host = host
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.set_access_token api_key
|
28
|
+
@@access_token = api_key
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.log
|
32
|
+
@@log
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.host
|
36
|
+
@@host
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.access_token
|
40
|
+
@@access_token
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: arii
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '1.0'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Pedro Lopes
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rest-client
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: nokogiri
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: jsonpath
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: 'ARiiP: integrate everything. Automated real-time integration & interoperability
|
84
|
+
platform.'
|
85
|
+
email:
|
86
|
+
- hello@pedrolopes.net
|
87
|
+
executables: []
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- ".gitignore"
|
92
|
+
- Gemfile
|
93
|
+
- Gemfile.lock
|
94
|
+
- LICENSE
|
95
|
+
- README.md
|
96
|
+
- Rakefile
|
97
|
+
- arii.gemspec
|
98
|
+
- lib/arii.rb
|
99
|
+
- lib/arii/agent.rb
|
100
|
+
- lib/arii/cashier.rb
|
101
|
+
- lib/arii/client.rb
|
102
|
+
- lib/arii/csvdetector.rb
|
103
|
+
- lib/arii/csvseedreader.rb
|
104
|
+
- lib/arii/detector.rb
|
105
|
+
- lib/arii/helper.rb
|
106
|
+
- lib/arii/jsondetector.rb
|
107
|
+
- lib/arii/jsonseedreader.rb
|
108
|
+
- lib/arii/seedreader.rb
|
109
|
+
- lib/arii/sqldetector.rb
|
110
|
+
- lib/arii/sqlseedreader.rb
|
111
|
+
- lib/arii/version.rb
|
112
|
+
- lib/arii/xmldetector.rb
|
113
|
+
- lib/arii/xmlseedreader.rb
|
114
|
+
- test/lib/i2x/version_test.rb
|
115
|
+
- test/test_helper.rb
|
116
|
+
homepage: http://ariip.com/
|
117
|
+
licenses:
|
118
|
+
- MIT
|
119
|
+
metadata: {}
|
120
|
+
post_install_message:
|
121
|
+
rdoc_options: []
|
122
|
+
require_paths:
|
123
|
+
- lib
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
requirements: []
|
135
|
+
rubyforge_project:
|
136
|
+
rubygems_version: 2.4.5
|
137
|
+
signing_key:
|
138
|
+
specification_version: 4
|
139
|
+
summary: arii client library for distributed agents.
|
140
|
+
test_files:
|
141
|
+
- test/lib/i2x/version_test.rb
|
142
|
+
- test/test_helper.rb
|