nonnative 1.22.0 → 1.23.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +19 -2
- data/lib/nonnative.rb +5 -0
- data/lib/nonnative/chaos_proxy.rb +15 -43
- data/lib/nonnative/close_all_socket_pair.rb +9 -0
- data/lib/nonnative/delay_socket_pair.rb +11 -0
- data/lib/nonnative/http_client.rb +12 -8
- data/lib/nonnative/invalid_data_socket_pair.rb +11 -0
- data/lib/nonnative/proxy.rb +1 -2
- data/lib/nonnative/socket_pair.rb +50 -0
- data/lib/nonnative/socket_pair_factory.rb +20 -0
- data/lib/nonnative/version.rb +1 -1
- metadata +11 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2265811d2fdb090bd12cb35065038272974519ad6a7758bb2b7c281ca7b804c1
|
4
|
+
data.tar.gz: c08f324e5de548b1457f3ff16585569f7917340b6367dc0b9d1cc1ceae2d4645
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dfe2d40e5c27f6d9425fbfc7059ce3d3723fdb00451a7a72a399d359627f7424699b044115848c45a7e180606919f81d03a439d6942acfbbcd8584350e35499a
|
7
|
+
data.tar.gz: 6b2221ac50779bf621e5377ae1940f0621e4f1b4d6349aead6f9adac575d37f9f3d04e12aa65f9118fdc8b277d8021e653566c77cc1dee2815ef501d8b936073
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -297,8 +297,8 @@ Nonnative.load_configuration('configuration.yml')
|
|
297
297
|
#### Proxies
|
298
298
|
|
299
299
|
We allow different proxies to be configured. These proxies can be used to simulate all kind of situations. The proxies that can be configured are:
|
300
|
-
- none (this is the default)
|
301
|
-
- chaos
|
300
|
+
- `none` (this is the default)
|
301
|
+
- `chaos`
|
302
302
|
|
303
303
|
Setup it up programmatically:
|
304
304
|
|
@@ -328,3 +328,20 @@ servers:
|
|
328
328
|
type: chaos
|
329
329
|
port: 20000
|
330
330
|
```
|
331
|
+
|
332
|
+
##### Fault Injection
|
333
|
+
|
334
|
+
The `chaos` proxy allows you to simulate failures by injecting them. We currently support the following:
|
335
|
+
- `close_all` - Closes the socket as soon as it connects.
|
336
|
+
- `delay` - This delays the communication between the connection.
|
337
|
+
- `invalid_data` - This takes the input and rearranges it to produce invalid data.
|
338
|
+
|
339
|
+
Setup it up programmatically:
|
340
|
+
|
341
|
+
```ruby
|
342
|
+
name = 'name of server in configuration'
|
343
|
+
server = Nonnative.pool.server_by_name(name)
|
344
|
+
|
345
|
+
server.proxy.close_all # To use close_all.
|
346
|
+
server.proxy.reset # To reset it back to a good state.
|
347
|
+
```
|
data/lib/nonnative.rb
CHANGED
@@ -35,6 +35,11 @@ require 'nonnative/proxy_factory'
|
|
35
35
|
require 'nonnative/proxy'
|
36
36
|
require 'nonnative/no_proxy'
|
37
37
|
require 'nonnative/chaos_proxy'
|
38
|
+
require 'nonnative/socket_pair'
|
39
|
+
require 'nonnative/close_all_socket_pair'
|
40
|
+
require 'nonnative/delay_socket_pair'
|
41
|
+
require 'nonnative/invalid_data_socket_pair'
|
42
|
+
require 'nonnative/socket_pair_factory'
|
38
43
|
|
39
44
|
module Nonnative
|
40
45
|
class << self
|
@@ -24,6 +24,14 @@ module Nonnative
|
|
24
24
|
apply_state :close_all
|
25
25
|
end
|
26
26
|
|
27
|
+
def delay
|
28
|
+
apply_state :delay
|
29
|
+
end
|
30
|
+
|
31
|
+
def invalid_data
|
32
|
+
apply_state :invalid_data
|
33
|
+
end
|
34
|
+
|
27
35
|
def reset
|
28
36
|
apply_state :none
|
29
37
|
end
|
@@ -38,57 +46,21 @@ module Nonnative
|
|
38
46
|
|
39
47
|
def perform_start
|
40
48
|
loop do
|
41
|
-
thread = Thread.start(tcp_server.accept)
|
49
|
+
thread = Thread.start(tcp_server.accept) do |local_socket|
|
50
|
+
SocketPairFactory.create(read_state, port).connect(local_socket)
|
51
|
+
connections.delete(Thread.current.object_id)
|
52
|
+
end
|
53
|
+
thread.report_on_exception = false
|
42
54
|
connections[thread.object_id] = thread
|
43
55
|
end
|
44
56
|
end
|
45
57
|
|
46
|
-
def connect(local_socket)
|
47
|
-
return local_socket.close if state?(:close_all)
|
48
|
-
|
49
|
-
remote_socket = create_remote_socket
|
50
|
-
return unless remote_socket
|
51
|
-
|
52
|
-
loop do
|
53
|
-
ready = select([local_socket, remote_socket], nil, nil)
|
54
|
-
|
55
|
-
break if write(ready, local_socket, remote_socket)
|
56
|
-
break if write(ready, remote_socket, local_socket)
|
57
|
-
end
|
58
|
-
rescue Errno::ECONNRESET
|
59
|
-
# Just ignore it.
|
60
|
-
ensure
|
61
|
-
local_socket.close
|
62
|
-
remote_socket&.close
|
63
|
-
connections.delete(Thread.current.object_id)
|
64
|
-
end
|
65
|
-
|
66
|
-
def create_remote_socket
|
67
|
-
timeout.perform do
|
68
|
-
::TCPSocket.new('0.0.0.0', port)
|
69
|
-
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
|
70
|
-
sleep 0.01
|
71
|
-
retry
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def write(ready, socket1, socket2)
|
76
|
-
if ready[0].include?(socket1)
|
77
|
-
data = socket1.recv(1024)
|
78
|
-
return true if data.empty?
|
79
|
-
|
80
|
-
socket2.write(data)
|
81
|
-
end
|
82
|
-
|
83
|
-
false
|
84
|
-
end
|
85
|
-
|
86
58
|
def apply_state(state)
|
87
59
|
mutex.synchronize { @state = state }
|
88
60
|
end
|
89
61
|
|
90
|
-
def
|
91
|
-
mutex.synchronize {
|
62
|
+
def read_state
|
63
|
+
mutex.synchronize { state }
|
92
64
|
end
|
93
65
|
end
|
94
66
|
end
|
@@ -8,31 +8,33 @@ module Nonnative
|
|
8
8
|
|
9
9
|
protected
|
10
10
|
|
11
|
-
def get(pathname, headers = {})
|
11
|
+
def get(pathname, headers = {}, timeout = 60)
|
12
12
|
with_exception do
|
13
13
|
uri = URI.join(host, pathname)
|
14
|
-
RestClient.get
|
14
|
+
RestClient::Request.execute(method: :get, url: uri.to_s, headers: headers, timeout: timeout)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
def post(pathname, payload, headers = {})
|
18
|
+
def post(pathname, payload, headers = {}, timeout = 60)
|
19
19
|
with_exception do
|
20
20
|
uri = URI.join(host, pathname)
|
21
|
-
RestClient.post
|
21
|
+
RestClient::Request.execute(method: :post, url: uri.to_s, payload: payload.to_json, headers: headers,
|
22
|
+
timeout: timeout)
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
25
|
-
def delete(pathname, headers = {})
|
26
|
+
def delete(pathname, headers = {}, timeout = 60)
|
26
27
|
with_exception do
|
27
28
|
uri = URI.join(host, pathname)
|
28
|
-
RestClient.delete
|
29
|
+
RestClient::Request.execute(method: :delete, url: uri.to_s, headers: headers, timeout: timeout)
|
29
30
|
end
|
30
31
|
end
|
31
32
|
|
32
|
-
def put(pathname, payload, headers = {})
|
33
|
+
def put(pathname, payload, headers = {}, timeout = 60)
|
33
34
|
with_exception do
|
34
35
|
uri = URI.join(host, pathname)
|
35
|
-
RestClient.put
|
36
|
+
RestClient::Request.execute(method: :put, url: uri.to_s, payload: payload.to_json, headers: headers,
|
37
|
+
timeout: timeout)
|
36
38
|
end
|
37
39
|
end
|
38
40
|
|
@@ -42,6 +44,8 @@ module Nonnative
|
|
42
44
|
|
43
45
|
def with_exception
|
44
46
|
yield
|
47
|
+
rescue RestClient::Exceptions::ReadTimeout => e
|
48
|
+
raise e
|
45
49
|
rescue RestClient::ExceptionWithResponse => e
|
46
50
|
e.response
|
47
51
|
end
|
data/lib/nonnative/proxy.rb
CHANGED
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nonnative
|
4
|
+
class SocketPair
|
5
|
+
def initialize(port)
|
6
|
+
@port = port
|
7
|
+
end
|
8
|
+
|
9
|
+
def connect(local_socket)
|
10
|
+
remote_socket = create_remote_socket
|
11
|
+
|
12
|
+
loop do
|
13
|
+
ready = select([local_socket, remote_socket], nil, nil)
|
14
|
+
|
15
|
+
break if pipe(ready, local_socket, remote_socket)
|
16
|
+
break if pipe(ready, remote_socket, local_socket)
|
17
|
+
end
|
18
|
+
ensure
|
19
|
+
local_socket.close
|
20
|
+
remote_socket&.close
|
21
|
+
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
|
25
|
+
attr_reader :port
|
26
|
+
|
27
|
+
def create_remote_socket
|
28
|
+
::TCPSocket.new('0.0.0.0', port)
|
29
|
+
end
|
30
|
+
|
31
|
+
def pipe(ready, socket1, socket2)
|
32
|
+
if ready[0].include?(socket1)
|
33
|
+
data = read(socket1)
|
34
|
+
return true if data.empty?
|
35
|
+
|
36
|
+
write socket2, data
|
37
|
+
end
|
38
|
+
|
39
|
+
false
|
40
|
+
end
|
41
|
+
|
42
|
+
def read(socket)
|
43
|
+
socket.recv(1024)
|
44
|
+
end
|
45
|
+
|
46
|
+
def write(socket, data)
|
47
|
+
socket.write(data)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nonnative
|
4
|
+
class SocketPairFactory
|
5
|
+
class << self
|
6
|
+
def create(type, port)
|
7
|
+
case type
|
8
|
+
when :close_all
|
9
|
+
CloseAllSocketPair.new(port)
|
10
|
+
when :delay
|
11
|
+
DelaySocketPair.new(port)
|
12
|
+
when :invalid_data
|
13
|
+
InvalidDataSocketPair.new(port)
|
14
|
+
else
|
15
|
+
SocketPair.new(port)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/nonnative/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nonnative
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.23.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Falkowski
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-07-
|
11
|
+
date: 2020-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -284,15 +284,18 @@ files:
|
|
284
284
|
- lib/nonnative.rb
|
285
285
|
- lib/nonnative/before.rb
|
286
286
|
- lib/nonnative/chaos_proxy.rb
|
287
|
+
- lib/nonnative/close_all_socket_pair.rb
|
287
288
|
- lib/nonnative/command.rb
|
288
289
|
- lib/nonnative/configuration.rb
|
289
290
|
- lib/nonnative/configuration_process.rb
|
290
291
|
- lib/nonnative/configuration_proxy.rb
|
291
292
|
- lib/nonnative/configuration_server.rb
|
293
|
+
- lib/nonnative/delay_socket_pair.rb
|
292
294
|
- lib/nonnative/error.rb
|
293
295
|
- lib/nonnative/grpc_server.rb
|
294
296
|
- lib/nonnative/http_client.rb
|
295
297
|
- lib/nonnative/http_server.rb
|
298
|
+
- lib/nonnative/invalid_data_socket_pair.rb
|
296
299
|
- lib/nonnative/manual.rb
|
297
300
|
- lib/nonnative/no_proxy.rb
|
298
301
|
- lib/nonnative/observability.rb
|
@@ -302,6 +305,8 @@ files:
|
|
302
305
|
- lib/nonnative/proxy_factory.rb
|
303
306
|
- lib/nonnative/server.rb
|
304
307
|
- lib/nonnative/service.rb
|
308
|
+
- lib/nonnative/socket_pair.rb
|
309
|
+
- lib/nonnative/socket_pair_factory.rb
|
305
310
|
- lib/nonnative/start_error.rb
|
306
311
|
- lib/nonnative/startup.rb
|
307
312
|
- lib/nonnative/stop_error.rb
|
@@ -313,7 +318,7 @@ homepage: https://github.com/alexfalkowski/nonnative
|
|
313
318
|
licenses:
|
314
319
|
- Unlicense
|
315
320
|
metadata: {}
|
316
|
-
post_install_message:
|
321
|
+
post_install_message:
|
317
322
|
rdoc_options: []
|
318
323
|
require_paths:
|
319
324
|
- lib
|
@@ -328,8 +333,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
328
333
|
- !ruby/object:Gem::Version
|
329
334
|
version: '0'
|
330
335
|
requirements: []
|
331
|
-
rubygems_version: 3.0.
|
332
|
-
signing_key:
|
336
|
+
rubygems_version: 3.0.8
|
337
|
+
signing_key:
|
333
338
|
specification_version: 4
|
334
339
|
summary: Allows you to keep using the power of ruby to test other systems
|
335
340
|
test_files: []
|