outliers 0.3.3 → 0.5.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -1
- data/README.md +21 -17
- data/lib/outliers/{credentials.rb → account.rb} +4 -4
- data/lib/outliers/cli/process.rb +53 -15
- data/lib/outliers/cli.rb +1 -1
- data/lib/outliers/collection.rb +24 -18
- data/lib/outliers/evaluation.rb +60 -32
- data/lib/outliers/exceptions.rb +10 -1
- data/lib/outliers/filters/aws/ec2/tags.rb +2 -2
- data/lib/outliers/handlers/json.rb +36 -0
- data/lib/outliers/handlers/outliers_api.rb +62 -0
- data/lib/outliers/handlers.rb +1 -0
- data/lib/outliers/provider.rb +7 -7
- data/lib/outliers/resources/aws/ec2/instance.rb +1 -1
- data/lib/outliers/resources/aws/elb/load_balancer.rb +1 -1
- data/lib/outliers/resources/aws/rds/db_instance.rb +1 -1
- data/lib/outliers/resources/aws/s3/bucket_collection.rb +1 -1
- data/lib/outliers/result.rb +32 -8
- data/lib/outliers/run.rb +9 -3
- data/lib/outliers/verifications/shared.rb +2 -2
- data/lib/outliers/version.rb +1 -1
- data/lib/outliers.rb +2 -1
- data/outliers.gemspec +1 -1
- data/reference.yaml +10 -10
- data/shared.yaml +1 -1
- data/spec/{credentials_spec.rb → account_spec.rb} +7 -7
- data/spec/collection_spec.rb +48 -7
- data/spec/evaluation_spec.rb +109 -47
- data/spec/fixtures/{credentials1.yml → account1.yml} +1 -1
- data/spec/fixtures/{credentials2.yml → account2.yml} +1 -1
- data/spec/handlers/outliers_api_spec.rb +61 -0
- data/spec/info_spec.rb +2 -2
- data/spec/provider_spec.rb +9 -9
- data/spec/results_spec.rb +65 -16
- data/spec/run_spec.rb +4 -4
- data/spec/spec_helper.rb +3 -3
- data/spec/verifications/shared_spec.rb +3 -3
- metadata +18 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e21b9c0b8c0b80d467c4deedbd9e2f0911b44fcc
|
4
|
+
data.tar.gz: e14dbca5caad874380dc33a7e2e8edebd4884556
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6aa6ca8c8f0bcd4a4923f9c89b61cf93c5224754fdce113b69c1f4f039d7cf97a1d9cacb68781081502d8ceaff50089368e7f174d8cc262eda6c6a3d8c5a0511
|
7
|
+
data.tar.gz: a957f1bd5eeb096f930ff27ecdaf864dbba496d2aa8732081a4921f7ddb87bfddd65f62c53045d718e641963e4dbd6436ba4558a5e6f71fb5866c8f2a25daa1e
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
[![Build Status](https://secure.travis-ci.org/brettweavnet/outliers.png)](http://travis-ci.org/brettweavnet/outliers)
|
2
|
+
[![Code Climate](https://codeclimate.com/github/brettweavnet/outliers.png)](https://codeclimate.com/github/brettweavnet/outliers)
|
2
3
|
|
3
4
|
# Outliers
|
4
5
|
|
@@ -6,32 +7,26 @@ A framework to detect misconfigurations (Outliers).
|
|
6
7
|
|
7
8
|
## Overview
|
8
9
|
|
9
|
-
To detect misconfigurations at scale, Outliers provides a framework for performing complex evaluations:
|
10
|
+
To detect misconfigurations at scale, Outliers provides a framework for performing complex evaluations of cloud resources based on the following:
|
10
11
|
|
11
12
|
* Applications rely on **resources** delivered from multiple **providers** (EC2, S3, etc).
|
12
13
|
* Resource configuration can be evaluated against specific **verifications** (Instance launched from given AMI, S3 bucket contains no public objects, etc).
|
13
14
|
* Verifications can be performed against a subset of resources based on a **filter**.
|
14
15
|
* Those not passing verification, are flagged as Outliers.
|
15
16
|
|
16
|
-
Evalutions are read from from files ending with **.rb** within a target directory.
|
17
|
-
|
18
|
-
Multiple evaluations can be specified in a file, with multiple files in directory.
|
19
|
-
|
20
17
|
## Requirements
|
21
18
|
|
22
|
-
* Ruby 1.9.3 or greater
|
19
|
+
* Ruby 1.9.3 or greater
|
23
20
|
|
24
21
|
## Installation
|
25
22
|
|
26
|
-
Install the gem:
|
27
|
-
|
28
23
|
gem install outliers
|
29
24
|
|
30
25
|
## Getting Started
|
31
26
|
|
32
|
-
Create **~/outliers.yml** with a list of
|
27
|
+
Create **~/outliers.yml** with a list of accounts in the following format:
|
33
28
|
|
34
|
-
|
29
|
+
account_name:
|
35
30
|
region: AWS_REGION
|
36
31
|
access_key_id: AWS_ACCESS_ID
|
37
32
|
secret_access_key: AWS_SECRET_KEY
|
@@ -43,11 +38,11 @@ For example:
|
|
43
38
|
access_key_id: abcd1234abcd1234abcd
|
44
39
|
secret_access_key: abcd1234abcd1234abcdabcd1234abcd1234abcd
|
45
40
|
|
46
|
-
|
41
|
+
Create a directory to store your evaluations.
|
47
42
|
|
48
43
|
mkdir ~/outliers
|
49
44
|
|
50
|
-
To verify all instances are in a VPC, create
|
45
|
+
To verify all instances in aws_prod are in a VPC, create ec2.rb in ~/outliers containing:
|
51
46
|
|
52
47
|
evaluate do
|
53
48
|
connect 'aws_prod', provider: 'aws_ec2'
|
@@ -76,13 +71,22 @@ Sample Output:
|
|
76
71
|
I, [2013-09-24T09:42:44.804147 #4940] INFO -- : Evaluations completed.
|
77
72
|
I, [2013-09-24T09:42:44.804211 #4940] INFO -- : (0 evaluations failed, 1 evaluations passed.)
|
78
73
|
|
79
|
-
|
80
|
-
|
74
|
+
## Results
|
75
|
+
|
76
|
+
To return outliers results, you must set the **OUTLIERS_KEY** environment variable.
|
77
|
+
|
78
|
+
export OUTLIERS_KEY=abcd1234
|
79
|
+
|
80
|
+
To modify the URL where reuslts are sent, set **OUTLIERS_URL** environment variable.
|
81
|
+
|
82
|
+
By default, results are sent to **https://api.getoutliers.com**
|
83
|
+
|
84
|
+
export OUTLIERS_URL=http://localhost:3000
|
81
85
|
|
82
86
|
## Examples
|
83
87
|
|
84
|
-
See [examples](http://
|
88
|
+
See [examples](http://www.getoutliers.com/documentation/examples) for a list of more advanced evaluations.
|
85
89
|
|
86
|
-
##
|
90
|
+
## Documentation
|
87
91
|
|
88
|
-
See
|
92
|
+
See [providers](http://www.getoutliers.com/documentation/providers), [resources](http://www.getoutliers.com/documentation/resources) and [filters](http://www.getoutliers.com/documentation/filters) for additional documentation.
|
@@ -1,14 +1,14 @@
|
|
1
1
|
module Outliers
|
2
|
-
module
|
2
|
+
module Account
|
3
3
|
module_function
|
4
4
|
|
5
5
|
def load_from_file(file)
|
6
|
-
|
6
|
+
account = {}
|
7
7
|
contents = File.read file
|
8
8
|
YAML.load(contents).each_pair do |k,v|
|
9
|
-
|
9
|
+
account[k] = v
|
10
10
|
end
|
11
|
-
|
11
|
+
account
|
12
12
|
end
|
13
13
|
|
14
14
|
end
|
data/lib/outliers/cli/process.rb
CHANGED
@@ -2,7 +2,7 @@ module Outliers
|
|
2
2
|
module CLI
|
3
3
|
class Process
|
4
4
|
def process
|
5
|
-
@options = { threads: 1 }
|
5
|
+
@options = { threads: 1, log_level: 'info' }
|
6
6
|
|
7
7
|
option_parser.parse!
|
8
8
|
|
@@ -16,31 +16,53 @@ module Outliers
|
|
16
16
|
@run.thread_count = @options[:threads]
|
17
17
|
end
|
18
18
|
|
19
|
+
log_level = @options.fetch(:log_level).upcase
|
20
|
+
|
21
|
+
unless ["DEBUG", "INFO", "WARN", "ERROR"].include? log_level
|
22
|
+
@logger.error "Invalid log level. Valid levels are debug, info, warn, error."
|
23
|
+
exit 1
|
24
|
+
end
|
25
|
+
|
26
|
+
@logger.level = Logger.const_get log_level
|
27
|
+
|
19
28
|
begin
|
20
|
-
@run.
|
29
|
+
@run.account = Account.load_from_file "#{ENV['HOME']}/.outliers.yml"
|
21
30
|
@run.process_evaluations_in_dir
|
22
31
|
rescue Outliers::Exceptions::Base => e
|
23
32
|
@logger.error e.message
|
24
33
|
exit 1
|
25
34
|
end
|
26
35
|
|
27
|
-
|
28
|
-
|
36
|
+
passing_count = @run.passing_results.count
|
37
|
+
failing_count = @run.failing_results.count
|
29
38
|
|
30
39
|
@logger.info "Evaluations completed."
|
31
40
|
|
32
|
-
|
33
|
-
|
34
|
-
|
41
|
+
if key
|
42
|
+
@logger.info "Running report handlers."
|
43
|
+
@run.results.each do |result|
|
44
|
+
unless Outliers::Handlers::OutliersApi.new.post result, key, results_url
|
45
|
+
@logger.error "Report handler failed."
|
46
|
+
exit 1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
@logger.info "Report handlers completed."
|
50
|
+
else
|
51
|
+
@logger.info "OUTLIERS_KEY not set, not sending results."
|
52
|
+
end
|
53
|
+
|
54
|
+
@run.failing_results.each do |r|
|
55
|
+
if r.name
|
56
|
+
@logger.info "Results of '#{r.name}', verifying '#{r.verification_name}' of '#{r.provider_name}:#{r.resource_name}' via '#{r.account_name}' failed."
|
35
57
|
else
|
36
|
-
@logger.info "Verification '#{
|
58
|
+
@logger.info "Verification '#{r.verification_name}' of '#{r.provider_name}:#{r.resource_name}' via '#{r.account_name}' failed."
|
37
59
|
end
|
38
|
-
@logger.info "Failing resource IDs '#{
|
60
|
+
@logger.info "Failing resource IDs '#{r.failing_resources.map{|r| r.id}.join(', ')}'"
|
39
61
|
end
|
40
62
|
|
41
|
-
@logger.info "(#{
|
63
|
+
@logger.info "(#{failing_count} evaluations failed, #{passing_count} evaluations passed.)"
|
42
64
|
|
43
|
-
exit 1 unless
|
65
|
+
exit 1 unless failing_count.zero?
|
44
66
|
end
|
45
67
|
|
46
68
|
def command_name
|
@@ -53,17 +75,33 @@ module Outliers
|
|
53
75
|
|
54
76
|
private
|
55
77
|
|
78
|
+
def key
|
79
|
+
ENV['OUTLIERS_KEY']
|
80
|
+
end
|
81
|
+
|
82
|
+
def url
|
83
|
+
ENV['OUTLIERS_URL'] ||= 'https://api.getoutliers.com'
|
84
|
+
end
|
85
|
+
|
86
|
+
def results_url
|
87
|
+
"#{url}/results"
|
88
|
+
end
|
89
|
+
|
56
90
|
def option_parser
|
57
91
|
OptionParser.new do |opts|
|
58
92
|
opts.banner = "Usage: outliers process [options]"
|
59
93
|
|
60
|
-
opts.on("-t", "--threads [THREADS]", "Maximum number of evaluations threads to run concurrently (Default: 1).") do |o|
|
61
|
-
@options[:threads] = o.to_i
|
62
|
-
end
|
63
|
-
|
64
94
|
opts.on("-d", "--directory [DIRECTORY]", "Directory containing evaluations to load.") do |o|
|
65
95
|
@options[:directory] = o
|
66
96
|
end
|
97
|
+
|
98
|
+
opts.on("-l", "--log_level [LOG_LEVEL]", "Log level (Default: info).") do |o|
|
99
|
+
@options[:log_level] = o
|
100
|
+
end
|
101
|
+
|
102
|
+
opts.on("-t", "--threads [THREADS]", "Maximum number of evaluations threads to run concurrently (Default: 1).") do |o|
|
103
|
+
@options[:threads] = o.to_i
|
104
|
+
end
|
67
105
|
end
|
68
106
|
end
|
69
107
|
|
data/lib/outliers/cli.rb
CHANGED
@@ -31,7 +31,7 @@ module Outliers
|
|
31
31
|
puts ''
|
32
32
|
puts 'Append -h for help on specific subcommand.'
|
33
33
|
puts ''
|
34
|
-
puts 'See http://
|
34
|
+
puts 'See http://www.getoutliers.com/documentation for documentation.'
|
35
35
|
puts ''
|
36
36
|
|
37
37
|
puts 'Commands:'
|
data/lib/outliers/collection.rb
CHANGED
@@ -43,36 +43,44 @@ module Outliers
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def exclude_by_key(exclusions)
|
46
|
-
@logger.info "Excluding the following resources: '#{exclusions.join(',')}'."
|
47
46
|
save = list.reject {|u| exclusions.include? u.public_send key}
|
48
47
|
@list = save
|
49
48
|
end
|
50
49
|
|
51
|
-
def filter(args)
|
50
|
+
def filter(action, args)
|
52
51
|
name = args.keys.first
|
53
52
|
value = args.fetch name
|
54
53
|
|
55
|
-
logger.info "Applying filter '#{name}' with value '#{value}'."
|
56
|
-
|
57
54
|
unless self.public_methods.include? "filter_#{name}".to_sym
|
58
55
|
raise Exceptions::UnknownFilter.new "Unknown filter '#{name}'."
|
59
56
|
end
|
60
57
|
|
61
58
|
filtered_list = self.public_send "filter_#{name}", value
|
62
59
|
|
63
|
-
|
64
|
-
|
65
|
-
|
60
|
+
case action
|
61
|
+
when 'include'
|
62
|
+
logger.info "Including resources filtered by '#{name}' with value '#{value}'."
|
63
|
+
logger.warn "No resources match filter." unless filtered_list.any?
|
64
|
+
@list = filtered_list & @list
|
65
|
+
when 'exclude'
|
66
|
+
logger.info "Excluding resources filtered by '#{name}' with value '#{value}'."
|
67
|
+
@list -= filtered_list
|
68
|
+
else
|
69
|
+
raise Exceptions::UnknownFilterAction.new "Filters must be either 'include' or 'exclude'."
|
70
|
+
end
|
66
71
|
end
|
67
72
|
|
68
|
-
def verify(name, arguments=
|
69
|
-
|
73
|
+
def verify(name, arguments=nil)
|
74
|
+
logger.debug "Verifying '#{name}'."
|
75
|
+
|
76
|
+
name += "?" unless name =~ /^.*\?$/
|
70
77
|
|
71
78
|
unless list.any?
|
72
79
|
return { failing_resources: [], passing_resources: [] }
|
73
80
|
end
|
74
81
|
|
75
|
-
|
82
|
+
set_target_resources name if targets.any?
|
83
|
+
|
76
84
|
logger.debug "Target resources '#{list_by_key.join(', ')}'."
|
77
85
|
|
78
86
|
unless verification_exists? name
|
@@ -124,7 +132,7 @@ module Outliers
|
|
124
132
|
end
|
125
133
|
|
126
134
|
def set_target_resources(verification)
|
127
|
-
logger.
|
135
|
+
logger.debug "Setting target resource(s) to '#{targets.join(', ')}'."
|
128
136
|
|
129
137
|
@list = list.select {|r| targets.include? r.id }
|
130
138
|
|
@@ -136,12 +144,10 @@ module Outliers
|
|
136
144
|
end
|
137
145
|
|
138
146
|
def send_resources_verification(verification, arguments)
|
139
|
-
set_target_resources verification if targets.any?
|
140
|
-
|
141
147
|
failing_resources = reject do |resource|
|
142
|
-
|
143
|
-
logger.debug "Verification of resource '#{resource.id}' #{
|
144
|
-
|
148
|
+
r = send_verification resource, verification, arguments
|
149
|
+
logger.debug "Verification of resource '#{resource.id}' #{r ? 'passed' : 'failed'}."
|
150
|
+
r
|
145
151
|
end
|
146
152
|
{ failing_resources: failing_resources, passing_resources: list - failing_resources }
|
147
153
|
end
|
@@ -153,12 +159,12 @@ module Outliers
|
|
153
159
|
|
154
160
|
def send_verification(object, verification, arguments)
|
155
161
|
if object.method(verification).arity.zero?
|
156
|
-
|
162
|
+
unless arguments.nil?
|
157
163
|
raise Outliers::Exceptions::NoArgumentRequired.new "Verification '#{verification}' does not require an arguments."
|
158
164
|
end
|
159
165
|
object.public_send verification
|
160
166
|
else
|
161
|
-
if arguments.
|
167
|
+
if arguments.nil?
|
162
168
|
raise Outliers::Exceptions::ArgumentRequired.new "Verification '#{verification}' requires arguments."
|
163
169
|
end
|
164
170
|
object.public_send verification, arguments
|
data/lib/outliers/evaluation.rb
CHANGED
@@ -1,63 +1,92 @@
|
|
1
1
|
module Outliers
|
2
2
|
class Evaluation
|
3
3
|
|
4
|
-
attr_reader :
|
4
|
+
attr_reader :resource_collection, :provider_name, :provider_name_array
|
5
5
|
|
6
6
|
def initialize(args)
|
7
7
|
@run = args[:run]
|
8
8
|
@name = args[:name]
|
9
9
|
end
|
10
10
|
|
11
|
-
def connect(
|
12
|
-
@
|
11
|
+
def connect(account_name, options={})
|
12
|
+
@account_name = account_name
|
13
|
+
@provider_name = merged_account(account_name, options).fetch 'provider'
|
13
14
|
|
14
|
-
logger.info "Connecting via '#{
|
15
|
+
logger.info "Connecting via '#{account_name}' to '#{@provider_name}'."
|
15
16
|
logger.info "Including connection options '#{options.map {|k,v| "#{k}=#{v}"}.join(',')}'." if options.any?
|
16
17
|
|
17
18
|
set_provider_name_array
|
18
19
|
|
19
|
-
@provider = Outliers::Provider.connect_to
|
20
|
+
@provider = Outliers::Provider.connect_to merged_account(account_name, options)
|
20
21
|
end
|
21
22
|
|
22
|
-
def resources(name, targets=
|
23
|
-
logger.
|
24
|
-
@collection = collection_object name
|
23
|
+
def resources(name, targets=nil)
|
24
|
+
logger.debug "Loading '#{name}' resource collection."
|
25
25
|
|
26
|
-
|
26
|
+
@resource_name = name
|
27
|
+
@resource_collection = collection_object name
|
27
28
|
|
28
|
-
|
29
|
-
|
30
|
-
collection.targets = targets_array
|
31
|
-
end
|
32
|
-
collection
|
29
|
+
load_targets targets
|
30
|
+
resource_collection
|
33
31
|
end
|
34
32
|
|
35
|
-
def
|
36
|
-
|
33
|
+
def filter(action, args)
|
34
|
+
resource_collection.filter action, args.keys_to_s
|
37
35
|
end
|
38
36
|
|
39
|
-
def
|
40
|
-
|
41
|
-
end
|
37
|
+
def verify(verification_name, arguments=nil)
|
38
|
+
@resources_loaded ||= resource_collection.load_all
|
42
39
|
|
43
|
-
|
44
|
-
@resources_loaded ||= collection.load_all
|
40
|
+
args_to_send = convert_verification_arguments arguments
|
45
41
|
|
46
|
-
verification_result =
|
42
|
+
verification_result = resource_collection.verify verification_name, args_to_send
|
47
43
|
|
48
|
-
result = Outliers::Result.new
|
44
|
+
result = Outliers::Result.new account_name: @account_name,
|
49
45
|
failing_resources: verification_result.fetch(:failing_resources),
|
46
|
+
name: @name,
|
50
47
|
passing_resources: verification_result.fetch(:passing_resources),
|
51
|
-
|
52
|
-
|
48
|
+
arguments: Array(args_to_send),
|
49
|
+
provider_name: @provider_name,
|
50
|
+
resource_name: @resource_name,
|
51
|
+
verification_name: verification_name
|
53
52
|
|
54
|
-
logger.info "Verification '#{
|
53
|
+
logger.info "Verification '#{verification_name}' #{result.passed? ? 'passed' : 'failed'}."
|
55
54
|
|
56
55
|
@run.results << result
|
57
56
|
end
|
58
57
|
|
59
58
|
private
|
60
59
|
|
60
|
+
def load_targets(targets)
|
61
|
+
case targets.class.to_s
|
62
|
+
when "Hash"
|
63
|
+
t = targets.keys_to_sym
|
64
|
+
if t.has_key? :include
|
65
|
+
list = Array(t.fetch :include)
|
66
|
+
logger.info "Targeting '#{list.join(', ')}' from '#{@resource_name}' collection."
|
67
|
+
resource_collection.targets = list
|
68
|
+
elsif t.has_key? :exclude
|
69
|
+
list = Array(t.fetch :exclude)
|
70
|
+
logger.info "Excluding '#{list.join(', ')}' from '#{@resource_name}' collection."
|
71
|
+
resource_collection.exclude_by_key list
|
72
|
+
else
|
73
|
+
logger.info "Targeting all resources in '#{@resource_name}' collection."
|
74
|
+
end
|
75
|
+
when "String", "Array"
|
76
|
+
list = Array(targets)
|
77
|
+
logger.info "Targeting '#{list.join(', ')}' from '#{@resource_name}' collection."
|
78
|
+
resource_collection.targets = list
|
79
|
+
when "Nil"
|
80
|
+
logger.info "Targeting all resources in '#{@resource_name}' collection."
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def convert_verification_arguments(arguments)
|
85
|
+
return Array(arguments) if arguments.is_a?(Array) || arguments.is_a?(String)
|
86
|
+
return nil if arguments.is_a?(NilClass)
|
87
|
+
raise Outliers::Exceptions::InvalidArguments.new "Verification arguments '#{arguments}' invalid. Must be a string or array."
|
88
|
+
end
|
89
|
+
|
61
90
|
def set_provider_name_array
|
62
91
|
begin
|
63
92
|
array = Outliers::Providers.name_map.fetch(provider_name).to_s.split('::')
|
@@ -75,13 +104,13 @@ module Outliers
|
|
75
104
|
raise Outliers::Exceptions::UnknownCollection.new "Unknown collection '#{name}'."
|
76
105
|
end
|
77
106
|
|
78
|
-
def
|
79
|
-
@run.
|
107
|
+
def account(name)
|
108
|
+
@run.account.fetch name
|
80
109
|
end
|
81
110
|
|
82
|
-
def
|
83
|
-
|
84
|
-
|
111
|
+
def merged_account(name, options)
|
112
|
+
account(name).merge! options.keys_to_s
|
113
|
+
account(name).merge :name => name
|
85
114
|
end
|
86
115
|
|
87
116
|
def logger
|
@@ -90,4 +119,3 @@ module Outliers
|
|
90
119
|
|
91
120
|
end
|
92
121
|
end
|
93
|
-
|
data/lib/outliers/exceptions.rb
CHANGED
@@ -12,16 +12,22 @@ module Outliers
|
|
12
12
|
class ArgumentRequired < Base
|
13
13
|
end
|
14
14
|
|
15
|
+
class HandlerError < Base
|
16
|
+
end
|
17
|
+
|
15
18
|
class InvalidBucket < Base
|
16
19
|
end
|
17
20
|
|
21
|
+
class InvalidArguments < Base
|
22
|
+
end
|
23
|
+
|
18
24
|
class NoArgumentRequired < Base
|
19
25
|
end
|
20
26
|
|
21
27
|
class UnknownCollection < Base
|
22
28
|
end
|
23
29
|
|
24
|
-
class
|
30
|
+
class UnknownAccount < Base
|
25
31
|
end
|
26
32
|
|
27
33
|
class UnknownVerification < Base
|
@@ -30,6 +36,9 @@ module Outliers
|
|
30
36
|
class UnknownFilter < Base
|
31
37
|
end
|
32
38
|
|
39
|
+
class UnknownFilterAction < Base
|
40
|
+
end
|
41
|
+
|
33
42
|
class UnknownProvider < Base
|
34
43
|
end
|
35
44
|
|
@@ -7,12 +7,12 @@ module Outliers
|
|
7
7
|
def filter_tag(value)
|
8
8
|
tag_name = value.split(':').first
|
9
9
|
tag_value = value.split(':').last
|
10
|
-
logger.info "
|
10
|
+
logger.info "Loading filter by tag '#{tag_name}' equals '#{tag_value}'."
|
11
11
|
list.select do |r|
|
12
12
|
if r.tags.has_key? tag_name
|
13
13
|
value = r.tags[tag_name]
|
14
14
|
result = value == tag_value
|
15
|
-
logger.debug "'#{r.id}' has tag with value '#{value}'. #{result ? 'Matches' : 'Does not match'} filter."
|
15
|
+
logger.debug "'#{r.id}' has tag '#{tag_name}' with value '#{value}'. #{result ? 'Matches' : 'Does not match'} filter."
|
16
16
|
result
|
17
17
|
else
|
18
18
|
logger.debug "'#{r.id}' does not have tag '#{tag_name}'"
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module Outliers
|
4
|
+
module Handlers
|
5
|
+
class JSON
|
6
|
+
def post(result)
|
7
|
+
host = 'localhost'
|
8
|
+
port = '3000'
|
9
|
+
path = '/results'
|
10
|
+
|
11
|
+
req = Net::HTTP::Post.new(path, initheader = { 'Content-Type' => 'application/json',
|
12
|
+
'Accept' => 'application/vnd.outliers-v1+json' })
|
13
|
+
req.body = result.to_json
|
14
|
+
|
15
|
+
response = Net::HTTP.new(host, port).start {|http| http.request(req) }
|
16
|
+
|
17
|
+
logger.debug response.body
|
18
|
+
|
19
|
+
if response
|
20
|
+
logger.debug "Handler completed succesfully."
|
21
|
+
true
|
22
|
+
else
|
23
|
+
logger.debug "Handler failed."
|
24
|
+
false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def logger
|
31
|
+
@logger ||= Outliers.logger
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'net/http'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module Outliers
|
6
|
+
module Handlers
|
7
|
+
class OutliersApi
|
8
|
+
def post(result, key, url)
|
9
|
+
uri = URI.parse url
|
10
|
+
|
11
|
+
host = uri.host
|
12
|
+
port = uri.port
|
13
|
+
path = uri.path
|
14
|
+
use_ssl = uri.scheme == 'https'
|
15
|
+
|
16
|
+
req = Net::HTTP::Post.new path, header
|
17
|
+
|
18
|
+
req.body = body(key, result)
|
19
|
+
|
20
|
+
logger.debug "Hanlder URL: #{url}"
|
21
|
+
logger.debug "Posting: #{body("XXX", result)}"
|
22
|
+
|
23
|
+
session = Net::HTTP.new(host, port)
|
24
|
+
session.use_ssl = use_ssl
|
25
|
+
|
26
|
+
begin
|
27
|
+
response = session.start {|http| http.request(req) }
|
28
|
+
rescue Errno::ECONNREFUSED
|
29
|
+
logger.error "Connection to '#{url}' refused."
|
30
|
+
return false
|
31
|
+
end
|
32
|
+
|
33
|
+
if response.code == "200"
|
34
|
+
logger.debug "Received: #{response.body}"
|
35
|
+
logger.debug "Handler completed succesfully."
|
36
|
+
true
|
37
|
+
else
|
38
|
+
logger.error "Received: #{response.body}"
|
39
|
+
logger.error "Handler failed with code #{response.code}."
|
40
|
+
false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def logger
|
47
|
+
@logger ||= Outliers.logger
|
48
|
+
end
|
49
|
+
|
50
|
+
def header
|
51
|
+
{ 'Content-Type' => 'application/json',
|
52
|
+
'Accept' => 'application/vnd.outliers-v1+json' }
|
53
|
+
end
|
54
|
+
|
55
|
+
def body(key, result)
|
56
|
+
{ 'key' => key,
|
57
|
+
'result' => result.to_hash }.to_json
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'outliers/handlers/outliers_api'
|