aranea 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ OTgzYzg1NjVhM2MyNzdiMDRkNzJkNzQ4MjMwMmI2ZDUzMWIzM2FkMg==
5
+ data.tar.gz: !binary |-
6
+ YmFmYjdjMTBkOWU2ZjljMGE1ZjcxM2FkMTY1M2E4MGQ4ZGU4ODMwOA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NGMyMDg3MjkxYzhhOGI4YzkwNGE0MDI4ZTk1ZDNmYTUzNjM0ZjkwNjhkMjM2
10
+ ODI4NTViMTk2ZDQzMWU5NjMxMTZkNjYyY2E3YWE3NDcxNDI3N2E3MGE2NDcw
11
+ NDViNWI3ZmYzZjJlMjViMDc5ZGEwN2VhYmRkYTIxNGY5NWNlZDg=
12
+ data.tar.gz: !binary |-
13
+ MTA0OTAyMGEyYzg4MzFiMzY1Njc4YTEzYzM4ZjMwYjNhZGI0OGIyMzFhMDJk
14
+ YzNhNjRkNDJhOWIyOWU2ZGI4MGQ0NzhkNzIwOTEzOGUxZjNiOWI4OGI3MjE1
15
+ MTI4NjUxOGY3NmZkZTU4NGRkZjhiYmZhMDhmYjY4MjQwODUzZjA=
@@ -0,0 +1,2 @@
1
+ require 'aranea/rack/aranea_middleware'
2
+ require 'aranea/faraday/aranea_middleware'
@@ -0,0 +1,95 @@
1
+ require 'faraday'
2
+ require 'active_support/core_ext/numeric/time'
3
+ module Aranea
4
+
5
+ # TODO: Look into moving whitelisting of consumer hostnames to here and allowing it to be configurable via the consuming application
6
+
7
+ class Failure
8
+
9
+ class << self
10
+
11
+ def current
12
+ retrieve_failure || NullFailure.new
13
+ end
14
+
15
+ def create(params)
16
+ if failure = retrieve_failure
17
+ raise FailureFailure, "A failure is already in progress (#{failure})."
18
+ else
19
+ failure = new(params)
20
+ Repository.store(failure, params[:minutes].minutes)
21
+ failure
22
+ end
23
+ end
24
+
25
+ def retrieve_failure
26
+ Repository.get
27
+ end
28
+
29
+ end
30
+
31
+ attr_accessor :expiration_date
32
+
33
+ def initialize(params)
34
+ @pattern = Regexp.new(params[:pattern])
35
+ @response = params[:failure]
36
+ end
37
+
38
+ def should_fail?(request_env, app)
39
+ @pattern.match(request_env[:url].to_s)
40
+ end
41
+
42
+ def respond!
43
+ if @response == 'timeout'
44
+ raise ::Faraday::Error::TimeoutError, 'Fake failure from Aranea'
45
+ else
46
+ ::Faraday::Response.new(status: @response.to_i, body: 'Fake failure from Aranea', response_headers: {})
47
+ end
48
+ end
49
+
50
+ def to_s
51
+ "Failure on #{@pattern.inspect} ending at approximately #@expiration_date"
52
+ end
53
+
54
+ #TODO: Actually implement Repository pattern, dependency injection and all.
55
+ # As is we only support sharing between multiple instances if Rails.cache exists and does
56
+ class Repository
57
+ @cache = if defined?(Rails::RAILS_CACHE) && Rails.cache
58
+ Rails.cache
59
+ else
60
+ require 'active_support/cache'
61
+ ActiveSupport::Cache::MemoryStore.new
62
+ end
63
+
64
+ KEY = 'aranea_current_failure'
65
+
66
+ class << self
67
+
68
+ def store(failure, lifespan)
69
+ failure.expiration_date = Time.now + lifespan
70
+ @cache.write(KEY, failure, expires_in: lifespan)
71
+ end
72
+
73
+ def get
74
+ @cache.read(KEY)
75
+ end
76
+
77
+ def clear
78
+ @cache.delete(KEY)
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+
85
+ end
86
+
87
+ class NullFailure
88
+
89
+ def should_fail?(request_env, app)
90
+ false
91
+ end
92
+
93
+ end
94
+
95
+ end
@@ -0,0 +1,30 @@
1
+ require 'aranea/failure_repository'
2
+
3
+ module Aranea
4
+ module Faraday
5
+
6
+ class FailureSimulator
7
+
8
+ def initialize(app, config = {})
9
+ @app = app
10
+ @config = config
11
+ end
12
+
13
+ def call(request_env)
14
+
15
+ current_failure = Failure.current
16
+
17
+ if current_failure.should_fail?(request_env, @app)
18
+ #TODO: injectable logger
19
+ puts "Aranea: simulating a failed call on #{request_env}"
20
+ current_failure.respond!
21
+ else
22
+ @app.call(request_env)
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,67 @@
1
+ require 'aranea/failure_repository'
2
+ require 'rack'
3
+
4
+ module Aranea
5
+
6
+ FailureFailure = Class.new(RuntimeError)
7
+
8
+ ALLOWED_MINUTES = 1..60
9
+
10
+ module Rack
11
+
12
+ class FailureCreator
13
+
14
+ def initialize(app, config = {})
15
+ @app = app
16
+ @config = config
17
+ end
18
+
19
+ def call(env)
20
+ if failure_creation_request?(env)
21
+ response = begin
22
+ [create_failure(::Rack::Utils.parse_query(env['QUERY_STRING'])), 201, {}]
23
+ rescue FailureFailure => e
24
+ [e.message, 422, {}]
25
+ rescue
26
+ [$!.message, 500, {}]
27
+ end
28
+ ::Rack::Response.new(*response).finish
29
+ else
30
+ @app.call(env)
31
+ end
32
+ end
33
+
34
+ protected
35
+
36
+ def failure_creation_request?(env)
37
+ env['REQUEST_METHOD'] == 'POST' && env['PATH_INFO'] == '/disable'
38
+ end
39
+
40
+ def create_failure(options)
41
+ dependency = options.fetch('dependency') { raise FailureFailure, 'Please provide a dependency to simulate failing' }
42
+ minutes = options.fetch('minutes') { 5 }
43
+ failure = options.fetch('failure') { '500' }
44
+
45
+ unless failure =~ /\A((4|5)\d\d|timeout)\Z/
46
+ raise FailureFailure, "failure should be a 4xx or 5xx status code or timeout, got #{failure}"
47
+ end
48
+
49
+ unless ALLOWED_MINUTES.cover?(minutes.to_i)
50
+ raise FailureFailure, "minutes should be an integer from #{ALLOWED_MINUTES.begin} to #{ALLOWED_MINUTES.end}, got #{minutes}"
51
+ end
52
+
53
+ Failure.create(pattern: dependency, minutes: minutes.to_i, failure: failure)
54
+
55
+ result = "For the next #{minutes} minutes, all requests to urls containing '#{dependency}' will #{failure}"
56
+
57
+ #TODO: injectable logger
58
+ puts "Aranea: #{result}"
59
+
60
+ result
61
+
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,5 @@
1
+ module Aranea
2
+
3
+ VERSION = '0.0.0'
4
+
5
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aranea
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Aaron Weiner
8
+ - Matthew Szenher
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-05-04 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: faraday
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ! '>='
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ! '>='
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rack
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ! '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ! '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: activesupport
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rails
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: rspec
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ! '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: timecop
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ! '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: debugger
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ! '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ description: Rack and Faraday middleware to temporarily disable connections to external
113
+ dependencies
114
+ email:
115
+ - AWeiner@mdsol.com
116
+ - MSzenher@mdsol.com
117
+ executables: []
118
+ extensions: []
119
+ extra_rdoc_files: []
120
+ files:
121
+ - lib/aranea/failure_repository.rb
122
+ - lib/aranea/faraday/aranea_middleware.rb
123
+ - lib/aranea/rack/aranea_middleware.rb
124
+ - lib/aranea/version.rb
125
+ - lib/aranea.rb
126
+ homepage: https://github.com/mdsol/aranea
127
+ licenses:
128
+ - MIT
129
+ metadata: {}
130
+ post_install_message:
131
+ rdoc_options: []
132
+ require_paths:
133
+ - lib
134
+ required_ruby_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ! '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ required_rubygems_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ! '>='
142
+ - !ruby/object:Gem::Version
143
+ version: 1.3.5
144
+ requirements: []
145
+ rubyforge_project:
146
+ rubygems_version: 2.1.10
147
+ signing_key:
148
+ specification_version: 4
149
+ summary: Middleware for fault tolerance testing
150
+ test_files: []
151
+ has_rdoc: