outliers 0.3.3 → 0.5.0.beta1
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 +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
|
[](http://travis-ci.org/brettweavnet/outliers)
|
2
|
+
[](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'
|