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 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
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in arii.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,17 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ arii (0.0.3)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ rake (10.1.1)
10
+
11
+ PLATFORMS
12
+ ruby
13
+
14
+ DEPENDENCIES
15
+ bundler (~> 1.5)
16
+ arii!
17
+ rake
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
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rake/testtask'
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << 'lib/arii'
8
+ t.test_files = FileList['test/lib/arii/*_test.rb']
9
+ t.verbose = true
10
+ end
11
+
12
+ task :default => :test
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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ module ARII
2
+ VERSION = "1.0"
3
+ end
@@ -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
@@ -0,0 +1,9 @@
1
+ require_relative '../../test_helper'
2
+
3
+ describe ARII do
4
+
5
+ it "must be defined" do
6
+ ARII::VERSION.wont_be_nil
7
+ end
8
+
9
+ end
@@ -0,0 +1,4 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest/pride'
3
+
4
+ require File.expand_path('../../lib/arii.rb', __FILE__)
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