nonnative 1.22.0 → 1.23.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 +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: []
|