outliers 0.2.0 → 0.3.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/README.md +6 -66
  4. data/lib/outliers/cli/process.rb +12 -3
  5. data/lib/outliers/cli.rb +0 -24
  6. data/lib/outliers/collection.rb +15 -15
  7. data/lib/outliers/filters/aws/ec2/tags.rb +1 -1
  8. data/lib/outliers/info.rb +12 -0
  9. data/lib/outliers/provider.rb +0 -4
  10. data/lib/outliers/providers/aws/cloud_formation.rb +1 -5
  11. data/lib/outliers/providers/aws/ec2.rb +1 -5
  12. data/lib/outliers/providers/aws/elb.rb +1 -5
  13. data/lib/outliers/providers/aws/iam.rb +1 -5
  14. data/lib/outliers/providers/aws/rds.rb +1 -5
  15. data/lib/outliers/providers/aws/s3.rb +1 -5
  16. data/lib/outliers/providers/aws/{base.rb → shared.rb} +0 -10
  17. data/lib/outliers/providers/aws/sqs.rb +1 -5
  18. data/lib/outliers/providers/aws.rb +1 -1
  19. data/lib/outliers/resources/aws/ec2/instance.rb +0 -16
  20. data/lib/outliers/resources/aws/ec2/security_group.rb +0 -7
  21. data/lib/outliers/resources/aws/elb/load_balancer.rb +0 -7
  22. data/lib/outliers/resources/aws/iam/user.rb +0 -10
  23. data/lib/outliers/resources/aws/rds/db_instance.rb +0 -10
  24. data/lib/outliers/resources/aws/s3/bucket.rb +0 -13
  25. data/lib/outliers/resources.rb +4 -0
  26. data/lib/outliers/run.rb +24 -8
  27. data/lib/outliers/verifications/shared.rb +4 -16
  28. data/lib/outliers/version.rb +1 -1
  29. data/lib/outliers.rb +1 -0
  30. data/reference.yaml +128 -0
  31. data/spec/collection_spec.rb +3 -3
  32. data/spec/filters/aws/ec2/tags_spec.rb +1 -1
  33. data/spec/info_spec.rb +41 -0
  34. data/spec/run_spec.rb +57 -10
  35. data/spec/verifications/shared_spec.rb +6 -6
  36. metadata +7 -6
  37. data/lib/outliers/cli/evaluate.rb +0 -136
  38. data/lib/outliers/cli/providers.rb +0 -29
  39. data/lib/outliers/cli/resources.rb +0 -60
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ca2a95007c8c6b9d85847b7c857e8e5f54e72859
4
- data.tar.gz: 273c267dc763814b17162cf394cc453e77ba2253
3
+ metadata.gz: 74e9cb409e6eef3f41b71f7546b03a331acd8e78
4
+ data.tar.gz: 3bf117be6746ca6f358e53b063c8c46226ad8d23
5
5
  SHA512:
6
- metadata.gz: efbb5c48979eafc1001695502ad892ae799517497b789e6b56d034b44e0e3cdf74fa40c950cf77e9fd329cd0afbe1fb4ab612497c6b0a33ab7d00e95c1b75cba
7
- data.tar.gz: a2a0da57894add6de86c37a749d172a8174476b12f1d8665ebe68df9b11c31271bab95de1c1171f401cc4f8a2619e9726ad426f62b66914ec0e1b280f8aa74e4
6
+ metadata.gz: 64869c01820ae1d1e323c9531bafd25c10d57ef2660b4b6f505967a81256b974e05d4f9e9732bbb31dc785c7116227651a65fa2100e2330b8715e2452562d4c9
7
+ data.tar.gz: c9e49150e28457a4152b9cb5572ab9851e34c3fcf9742782d50a12afbc0043cacbb2b740addcc740256991486a4efeca4bb5ec721ae828c445d952665b5e00e6
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## HEAD
2
+
3
+ ## 0.3.0
4
+
5
+ * Remove CLI support
6
+ * Pull resource and provider info from reference.yaml
7
+ * Support running multiple evaluation threads
8
+
1
9
  ## 0.2.0
2
10
 
3
11
  * Added filters
data/README.md CHANGED
@@ -9,8 +9,8 @@ Outliers is a framework for verifying configuration of resources.
9
9
  * Applications and teams rely on multiple service providers (AWS, etc).
10
10
  * Providers deliver like resources with complex configuration (EC2 Instances, S3 Buckets, etc).
11
11
  * Resource configuration can be verified (launched from given AMI, contain private objects, etc).
12
- * The resources can be included or excluded by their ID (Instance ID, Object Key, etc).
13
- * Resources can be included in the list by matching a filter (Instance has tag 'x' with value 'y').
12
+ * Resources can be targeted or excluded by their ID (Instance ID, Object Key, etc).
13
+ * Resources can be targeted or excluded by matching a filter (Instance has tag 'x' with value 'y').
14
14
  * Those not passing verifications, are flagged as Outliers.
15
15
 
16
16
  ## Requirements
@@ -47,53 +47,9 @@ Multiple accounts can be specified, to add a prod and preprod AWS account:
47
47
 
48
48
  Depending on the provider, different keys and values are required.
49
49
 
50
- For a list of providers:
51
-
52
- outliers providers
53
-
54
50
  ## Usage
55
51
 
56
- Outliers can be used in two modes, as a **CLI** or a **DSL**.
57
-
58
- The CLI is good for testing and quick verifications.
59
-
60
- The DSL can be used to build up comprehensive list of verifications for a project or company.
61
-
62
- ### CLI
63
-
64
- To verify all EC2 instances are in a VPC:
65
-
66
- outliers evaluate -c aws_prod -p aws_ec2 -r instance -v vpc
67
-
68
- Credential keys can be overriden. To specify region us-west-1.
69
-
70
- outliers evaluate -c aws_prod -p aws_ec2 -r instance -v vpc -c region=us-west-1
71
-
72
- Verifications may require arguments. To verify your RDS databases have a 2 day retention period:
73
-
74
- outliers evaluate -c aws_prod -p aws_rds -r db_instance -v backup_retention_period -a days=2
75
-
76
- Verifications may accept multiple values for an argument. Values are separated by commas.
77
-
78
- To verify EC2 instances are launched from a list of known images:
79
-
80
- outliers evaluate -c aws_prod -p aws_ec2 -r instance -v valid_image_id -a image_ids=ami-12345678,ami-87654321
81
-
82
- To only target a specific resource:
83
-
84
- outliers evaluate -c aws_prod -p aws_ec2 -r instance -t i-87654321
85
-
86
- To exclude resources that are known exceptions:
87
-
88
- outliers evaluate -c aws_prod -p aws_ec2 -r instance -e i-12345678
89
-
90
- Resources have attributes which can be used to filter target resources. To filter instances who have tag 'Name' equal to 'web'.
91
-
92
- outliers evaluate -c aws_prod -p aws_ec2 -r instance -f 'tag=Name:web'
93
-
94
- ### DSL
95
-
96
- To run Outliers as a DSL
52
+ Outlier's DSL can be used to build up comprehensive list of verifications for a project or application.
97
53
 
98
54
  * Create a directory to store your evaluations.
99
55
  * Evalutions are read from from files within the directory.
@@ -195,7 +151,9 @@ Sometimes you want to exclude resources that are known exceptions, to exclude an
195
151
  verify 'valid_image_id', image_ids: ['ami-12345678','ami-87654321']
196
152
  end
197
153
 
198
- Resources have attributes which can be used to filter target resources. To filter instances who have tag 'Name' equal to 'web'.
154
+ Resources have attributes which can be used to filter target resources.
155
+
156
+ To filter instances who have tag 'Name' equal to 'web'.
199
157
 
200
158
  evaluate do
201
159
  connect 'aws_prod', provider: 'aws_ec2', region: 'us-west-1'
@@ -204,24 +162,6 @@ Resources have attributes which can be used to filter target resources. To filte
204
162
  verify 'valid_image_id', image_ids: ['ami-12345678','ami-87654321']
205
163
  end
206
164
 
207
- ### Help
208
-
209
- For a list of providers and required credentials:
210
-
211
- outliers providers
212
-
213
- For a list of resources, and available verifications, for a given provider:
214
-
215
- outliers resources -p PROVIDER_NAME
216
-
217
- For a fule list of commands run:
218
-
219
- outliers -h
220
-
221
- For full help on a command, append -h:
222
-
223
- outliers evaluate -h
224
-
225
165
  ## Contributing
226
166
 
227
167
  1. Fork it
@@ -2,7 +2,7 @@ module Outliers
2
2
  module CLI
3
3
  class Process
4
4
  def process
5
- @options = {}
5
+ @options = { threads: 1 }
6
6
 
7
7
  option_parser.parse!
8
8
 
@@ -11,9 +11,14 @@ module Outliers
11
11
  @logger = Outliers.logger
12
12
  @run = Run.new
13
13
 
14
+ if @options[:threads] > 1
15
+ @run.threaded = true
16
+ @run.thread_count = @options[:threads]
17
+ end
18
+
14
19
  begin
15
20
  @run.credentials = Credentials.load_from_file "#{ENV['HOME']}/.outliers.yml"
16
- @run.process_evaluations_in_config_folder
21
+ @run.process_evaluations_in_dir
17
22
  rescue Outliers::Exceptions::Base => e
18
23
  @logger.error e.message
19
24
  exit 1
@@ -26,7 +31,7 @@ module Outliers
26
31
 
27
32
  @run.failed.each do |f|
28
33
  @logger.info "Evaluation '#{f.evaluation}' verification '#{f.verification}' of '#{f.resource}' failed."
29
- @logger.debug "Failing resource IDs '#{f.failing_resources.map{|r| r.id}.join(', ')}'"
34
+ @logger.info "Failing resource IDs '#{f.failing_resources.map{|r| r.id}.join(', ')}'"
30
35
  end
31
36
 
32
37
  @logger.info "(#{failed} evaluations failed, #{passed} evaluations passed.)"
@@ -48,6 +53,10 @@ module Outliers
48
53
  OptionParser.new do |opts|
49
54
  opts.banner = "Usage: outliers process [options]"
50
55
 
56
+ opts.on("-t", "--threads [THREADS]", "Maximum number of evaluations threads to run concurrently (Default: 1).") do |o|
57
+ @options[:threads] = o.to_i
58
+ end
59
+
51
60
  opts.on("-d", "--directory [DIRECTORY]", "Directory containing evaluations to load.") do |o|
52
61
  @options[:directory] = o
53
62
  end
data/lib/outliers/cli.rb CHANGED
@@ -1,9 +1,6 @@
1
1
  require 'optparse'
2
2
 
3
- require 'outliers/cli/evaluate'
4
3
  require 'outliers/cli/process'
5
- require 'outliers/cli/providers'
6
- require 'outliers/cli/resources'
7
4
 
8
5
  module Outliers
9
6
  module CLI
@@ -12,20 +9,6 @@ module Outliers
12
9
  cmd = ARGV.shift
13
10
 
14
11
  case cmd
15
- when 'evaluate'
16
- begin
17
- CLI::Evaluate.new.evaluate
18
- rescue OptionParser::MissingArgument => e
19
- puts e.message
20
- exit 1
21
- end
22
- when 'providers'
23
- begin
24
- CLI::Providers.new.providers
25
- rescue OptionParser::MissingArgument => e
26
- puts e.message
27
- exit 1
28
- end
29
12
  when 'process'
30
13
  begin
31
14
  CLI::Process.new.process
@@ -33,13 +16,6 @@ module Outliers
33
16
  puts e.message
34
17
  exit 1
35
18
  end
36
- when 'resources'
37
- begin
38
- CLI::Resources.new.resources
39
- rescue OptionParser::MissingArgument => e
40
- puts e.message
41
- exit 1
42
- end
43
19
  when '-v'
44
20
  puts OUTLIERS::VERSION
45
21
  else
@@ -37,15 +37,15 @@ module Outliers
37
37
  end
38
38
 
39
39
  def each &block
40
- all.each do |resource|
40
+ list.each do |resource|
41
41
  block.call resource
42
42
  end
43
43
  end
44
44
 
45
45
  def exclude_by_key(exclusions)
46
46
  @logger.info "Excluding the following resources: '#{exclusions.join(',')}'."
47
- save = all.reject {|u| exclusions.include? u.public_send key}
48
- @all = save
47
+ save = list.reject {|u| exclusions.include? u.public_send key}
48
+ @list = save
49
49
  end
50
50
 
51
51
  def filter(args)
@@ -62,18 +62,18 @@ module Outliers
62
62
 
63
63
  logger.warn "No resources match filter." unless filtered_list.any?
64
64
 
65
- @all = filtered_list
65
+ @list = filtered_list
66
66
  end
67
67
 
68
68
  def verify(name, arguments={})
69
69
  name << "?" unless name =~ /^.*\?$/
70
70
 
71
- unless all.any?
71
+ unless list.any?
72
72
  return { failing_resources: [], passing_resources: [] }
73
73
  end
74
74
 
75
75
  logger.info "Verifying '#{name}'."
76
- logger.debug "Target resources '#{all_by_key.join(', ')}'."
76
+ logger.debug "Target resources '#{list_by_key.join(', ')}'."
77
77
 
78
78
  unless verification_exists? name
79
79
  raise Exceptions::UnknownVerification.new "Unkown verification '#{name}'."
@@ -86,8 +86,8 @@ module Outliers
86
86
  end
87
87
  end
88
88
 
89
- def all
90
- @all ||= load_all
89
+ def list
90
+ @list ||= load_all
91
91
  end
92
92
 
93
93
  def key
@@ -107,8 +107,8 @@ module Outliers
107
107
  m.include? name.to_sym
108
108
  end
109
109
 
110
- def all_by_key
111
- all.map {|r| r.public_send key}
110
+ def list_by_key
111
+ list.map {|r| r.public_send key}
112
112
  end
113
113
 
114
114
  def connect
@@ -126,13 +126,13 @@ module Outliers
126
126
  def set_target_resources(verification)
127
127
  logger.info "Verifying target '#{targets.join(', ')}'."
128
128
 
129
- @all = all.select {|r| targets.include? r.id }
129
+ @list = list.select {|r| targets.include? r.id }
130
130
 
131
- unless all.any?
131
+ unless list.any?
132
132
  raise Outliers::Exceptions::TargetNotFound.new "No resources found matching one or more of '#{targets}'."
133
133
  end
134
134
 
135
- @all
135
+ @list
136
136
  end
137
137
 
138
138
  def send_resources_verification(verification, arguments)
@@ -143,12 +143,12 @@ module Outliers
143
143
  logger.debug "Verification of resource '#{resource.id}' #{result ? 'passed' : 'failed'}."
144
144
  result
145
145
  end
146
- { failing_resources: failing_resources, passing_resources: all - failing_resources }
146
+ { failing_resources: failing_resources, passing_resources: list - failing_resources }
147
147
  end
148
148
 
149
149
  def send_collection_verification(verification, arguments)
150
150
  failing_resources = send_verification(self, verification, arguments)
151
- { failing_resources: failing_resources, passing_resources: all - failing_resources }
151
+ { failing_resources: failing_resources, passing_resources: list - failing_resources }
152
152
  end
153
153
 
154
154
  def send_verification(object, verification, arguments)
@@ -8,7 +8,7 @@ module Outliers
8
8
  tag_name = value.split(':').first
9
9
  tag_value = value.split(':').last
10
10
  logger.info "Filtering by tag '#{tag_name}' equals '#{tag_value}'."
11
- all.select do |r|
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
@@ -0,0 +1,12 @@
1
+ require 'yaml'
2
+
3
+ module Outliers
4
+ module Info
5
+ module_function
6
+
7
+ def reference
8
+ YAML.load_file(File.expand_path(File.join(File.dirname(__FILE__), '../../reference.yaml')))
9
+ end
10
+
11
+ end
12
+ end
@@ -14,10 +14,6 @@ module Outliers
14
14
  (self.to_s.split('::') - ['Outliers', 'Providers']).map { |p| p.underscore }.join('_').downcase
15
15
  end
16
16
 
17
- def self.credential_arguments
18
- {}
19
- end
20
-
21
17
  def initialize(credentials)
22
18
  @credentials = credentials
23
19
  @logger = Outliers.logger
@@ -5,12 +5,8 @@ module Outliers
5
5
 
6
6
  include Shared
7
7
 
8
- def self.credential_arguments
9
- Shared.credential_arguments
10
- end
11
-
12
8
  def connect
13
- logger.info "Connecting to region '#{@region}'." unless @cf
9
+ logger.debug "Connecting to region '#{@region}'." unless @cf
14
10
  @cf ||= ::AWS::CloudFormation.new config
15
11
  end
16
12
 
@@ -5,12 +5,8 @@ module Outliers
5
5
 
6
6
  include Shared
7
7
 
8
- def self.credential_arguments
9
- Shared.credential_arguments
10
- end
11
-
12
8
  def connect
13
- logger.info "Connecting to region '#{@region}'." unless @ec2
9
+ logger.debug "Connecting to region '#{@region}'." unless @ec2
14
10
  @ec2 ||= ::AWS::EC2.new config
15
11
  end
16
12
 
@@ -5,12 +5,8 @@ module Outliers
5
5
 
6
6
  include Shared
7
7
 
8
- def self.credential_arguments
9
- Shared.credential_arguments
10
- end
11
-
12
8
  def connect
13
- logger.info "Connecting to region '#{@region}'." unless @elb
9
+ logger.debug "Connecting to region '#{@region}'." unless @elb
14
10
  @elb ||= ::AWS::ELB.new config
15
11
  end
16
12
 
@@ -5,12 +5,8 @@ module Outliers
5
5
 
6
6
  include Shared
7
7
 
8
- def self.credential_arguments
9
- Shared.credential_arguments
10
- end
11
-
12
8
  def connect
13
- logger.info "Connecting to region '#{@region}'." unless @iam
9
+ logger.debug "Connecting to region '#{@region}'." unless @iam
14
10
  @iam ||= ::AWS::IAM.new config
15
11
  end
16
12
 
@@ -5,12 +5,8 @@ module Outliers
5
5
 
6
6
  include Shared
7
7
 
8
- def self.credential_arguments
9
- Shared.credential_arguments
10
- end
11
-
12
8
  def connect
13
- logger.info "Connecting to region '#{@region}'." unless @rds
9
+ logger.debug "Connecting to region '#{@region}'." unless @rds
14
10
  @rds ||= ::AWS::RDS.new config
15
11
  end
16
12
 
@@ -5,12 +5,8 @@ module Outliers
5
5
 
6
6
  include Shared
7
7
 
8
- def self.credential_arguments
9
- Shared.credential_arguments
10
- end
11
-
12
8
  def connect
13
- logger.info "Connecting to region '#{@region}'." unless @iam
9
+ logger.debug "Connecting to region '#{@region}'." unless @iam
14
10
  @iam ||= ::AWS::S3.new config
15
11
  end
16
12
 
@@ -17,16 +17,6 @@ module Outliers
17
17
  :region => @region }
18
18
  end
19
19
 
20
- module_function
21
-
22
- def credential_arguments
23
- {
24
- 'access_key_id' => 'AWS Account Access Key',
25
- 'secret_access_key' => 'AWS Account Secret Key',
26
- 'region' => 'AWS Region (Default us-east-1)'
27
- }
28
- end
29
-
30
20
  end
31
21
  end
32
22
  end
@@ -5,12 +5,8 @@ module Outliers
5
5
 
6
6
  include Shared
7
7
 
8
- def self.credential_arguments
9
- Shared.credential_arguments
10
- end
11
-
12
8
  def connect
13
- logger.info "Connecting to region '#{@region}'." unless @sqs
9
+ logger.debug "Connecting to region '#{@region}'." unless @sqs
14
10
  @sqs ||= ::AWS::SQS.new config
15
11
  end
16
12
 
@@ -1,4 +1,4 @@
1
- require 'outliers/providers/aws/base'
1
+ require 'outliers/providers/aws/shared'
2
2
 
3
3
  require 'outliers/providers/aws/cloud_formation'
4
4
  require 'outliers/providers/aws/ec2'
@@ -7,22 +7,6 @@ module Outliers
7
7
  'instance_id'
8
8
  end
9
9
 
10
- def self.verifications
11
- [
12
- { name: 'classic',
13
- description: 'Instance is in AWS Classic (No VPC).' },
14
- { name: 'source_dest_check',
15
- description: 'Instance source dest check set to true.' },
16
- { name: 'running',
17
- description: 'Instance status is running.' },
18
- { name: 'valid_image_id',
19
- description: 'ami_ids=ami_id1,ami_id2 - Instances Image ID (AMI) is in given list.',
20
- args: 'image_ids: [IMAGE_ID1, IMAGEID2]' },
21
- { name: 'vpc',
22
- description: 'Instance is in a VPC.' }
23
- ]
24
- end
25
-
26
10
  def classic?
27
11
  !vpc?
28
12
  end
@@ -3,13 +3,6 @@ module Outliers
3
3
  module Aws
4
4
  module Ec2
5
5
  class SecurityGroup < Resource
6
- def self.verifications
7
- [
8
- { name: 'no_public_internet_ingress',
9
- description: 'Security Group has no rules open to "0.0.0.0/0".' }
10
- ]
11
- end
12
-
13
6
  def no_public_internet_ingress?
14
7
  logger.debug "Verifying '#{id}'."
15
8
  source.ip_permissions.select do |i|
@@ -3,13 +3,6 @@ module Outliers
3
3
  module Aws
4
4
  module Elb
5
5
  class LoadBalancer < Resource
6
- def self.verifications
7
- [
8
- { name: 'ssl_certificates_valid',
9
- description: 'Validates all SSL certificates associated with an ELB are valid for given number of days',
10
- args: 'days: DAYS' }
11
- ]
12
- end
13
6
 
14
7
  def ssl_certificates_valid?(args)
15
8
  days = args[:days]
@@ -3,16 +3,6 @@ module Outliers
3
3
  module Aws
4
4
  module Iam
5
5
  class User < Resource
6
- def self.verifications
7
- [
8
- { name: 'mfa_enabled',
9
- description: 'Verify MFA enabled for user.' },
10
- { name: 'no_access_keys',
11
- description: 'Verify user has no access keys.' },
12
- { name: 'no_password_set',
13
- description: 'Verify password not set for user.' }
14
- ]
15
- end
16
6
 
17
7
  def no_access_keys?
18
8
  logger.debug "#{id} has #{access_keys.count} access key(s)."
@@ -7,16 +7,6 @@ module Outliers
7
7
  'db_instance_identifier'
8
8
  end
9
9
 
10
- def self.verifications
11
- [
12
- { name: 'backup_retention_period',
13
- description: 'Validate the backup retention period equals given days for the db_instance.',
14
- args: 'days: DAYS' },
15
- { name: 'multi_az',
16
- description: 'RDS Multi AZ set to yes.' }
17
- ]
18
- end
19
-
20
10
  def backup_retention_period?(args)
21
11
  days = args[:days]
22
12
 
@@ -4,19 +4,6 @@ module Outliers
4
4
  module S3
5
5
  class Bucket < Resource
6
6
 
7
- def self.verifications
8
- [
9
- { name: 'empty',
10
- description: 'Bucket has no objects.' },
11
- { name: 'no_public_objects',
12
- description: 'Bucket has no public accessible objects.' },
13
- { name: 'configured_as_website',
14
- description: 'Bucket is configured as a website.' },
15
- { name: 'not_configured_as_website',
16
- description: 'Bucket is not configured as a website.' }
17
- ]
18
- end
19
-
20
7
  def empty?
21
8
  logger.debug "Bucket #{id} has #{count} objects."
22
9
 
@@ -4,6 +4,10 @@ module Outliers
4
4
  module Resources
5
5
  module_function
6
6
 
7
+ def list
8
+ Outliers::Resources.collections
9
+ end
10
+
7
11
  def collections
8
12
  all_the_modules.select {|m| (m.is_a? Class) && (m.to_s =~ /Collection$/)}
9
13
  end
data/lib/outliers/run.rb CHANGED
@@ -1,24 +1,35 @@
1
1
  module Outliers
2
2
  class Run
3
- attr_accessor :credentials, :results
4
-
5
- def initialize
6
- @results = []
3
+ attr_accessor :credentials, :results, :threads, :threaded, :thread_count
4
+
5
+ def initialize(options={})
6
+ @results = []
7
+ @threads = []
8
+ @threaded = false
9
+ @thread_count = 1
10
+ Thread.abort_on_exception = true
7
11
  end
8
12
 
9
- def process_evaluations_in_config_folder
10
- evaluations_path = File.join Outliers.config_path
11
- files = Dir.glob(File.join(evaluations_path, '**', '*'))
13
+ def process_evaluations_in_dir
12
14
  files.each do |file|
13
15
  next if File.directory? file
14
16
  next if File.extname(file) != '.rb'
15
17
  logger.info "Processing '#{file}'."
16
18
  self.instance_eval File.read(file)
17
19
  end
20
+
21
+ threads.each {|t| t.join}
18
22
  end
19
23
 
20
24
  def evaluate(name='unspecified', &block)
21
- Evaluation.new(:name => name, :run => self).instance_eval &block
25
+ while Thread.list.count > thread_count
26
+ logger.info "Maximum concurrent threads running, sleeping."
27
+ sleep 2
28
+ end
29
+
30
+ evaluation = Proc.new { Evaluation.new(:name => name, :run => self).instance_eval &block }
31
+
32
+ threaded ? threads << Thread.new { evaluation.call } : evaluation.call
22
33
  end
23
34
 
24
35
  def passed
@@ -31,6 +42,11 @@ module Outliers
31
42
 
32
43
  private
33
44
 
45
+ def files
46
+ evaluations_path = File.join Outliers.config_path
47
+ files = Dir.glob File.join(evaluations_path, '**', '*')
48
+ end
49
+
34
50
  def logger
35
51
  @logger ||= Outliers.logger
36
52
  end