aranea 0.0.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 +15 -0
- data/lib/aranea.rb +2 -0
- data/lib/aranea/failure_repository.rb +95 -0
- data/lib/aranea/faraday/aranea_middleware.rb +30 -0
- data/lib/aranea/rack/aranea_middleware.rb +67 -0
- data/lib/aranea/version.rb +5 -0
- metadata +151 -0
checksums.yaml
ADDED
@@ -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=
|
data/lib/aranea.rb
ADDED
@@ -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
|
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:
|