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.
@@ -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: