nonnative 1.11.0 → 1.16.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4a5cb014d7be492fca744eb85ac93dc367935a8ac2e3693e133833597a3bd549
4
- data.tar.gz: ff5f799bb3dd66da7d9d933b0c16a596e43841a9bbcb2c87573de03a1dbf5f2f
3
+ metadata.gz: 06c156ebea189af501939979653772a2f87dcb6c262f373134d061bd0f07a48c
4
+ data.tar.gz: 6d41fd8ac177d6565517423c73b031c0c4e03512f2406e7be6f12e2611dfe87d
5
5
  SHA512:
6
- metadata.gz: ca60a62a4fffa470f50afabe68e51eb3ed93c139c06c4f6cd12a061058c7ef92f75e025ae4fa4eaeae456a47511a97f305c5d3dcdbfb8f090406f2567db4ccc1
7
- data.tar.gz: 53b1f5fba7553ccac0cfada04affa93e0cf7c22c9778d807b70376f5fa7f542b61d262311daac903ae3d929828fcfaac6f053a91377b4b8cf2c4124c4e5fbe79
6
+ metadata.gz: a34000c945bc7902645dd32a381311160353193efce3fcc9fbdc563a9e191b192b5e14b72bb4c1efa9d87a821558b801ba002d213e5aad7dceeef1f1ebf12e92
7
+ data.tar.gz: 9d31997089ebaf6e01b4394b4b13d916791e8d5366acb0fd78e09db3cc662609202d1ac0d6ed605dda35796eae84201f607e5255cf6a25e8e2dedd01ef87e43d
@@ -8,6 +8,12 @@ Layout/LineLength:
8
8
  Metrics/MethodLength:
9
9
  Max: 15
10
10
 
11
+ Metrics/BlockLength:
12
+ Max: 35
13
+
14
+ Metrics/AbcSize:
15
+ Max: 20
16
+
11
17
  Style/Documentation:
12
18
  Enabled: false
13
19
 
@@ -37,3 +43,18 @@ Layout/EmptyLinesAroundAttributeAccessor:
37
43
 
38
44
  Style/SlicingWithRange:
39
45
  Enabled: true
46
+
47
+ Lint/DeprecatedOpenSSLConstant:
48
+ Enabled: true
49
+
50
+ Lint/MixedRegexpCaptureTypes:
51
+ Enabled: true
52
+
53
+ Style/RedundantRegexpCharacterClass:
54
+ Enabled: true
55
+
56
+ Style/RedundantRegexpEscape:
57
+ Enabled: true
58
+
59
+ Style/RedundantFetchBlock:
60
+ Enabled: true
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nonnative (1.11.0)
4
+ nonnative (1.16.0)
5
5
  cucumber (~> 3.1, >= 3.1.2)
6
6
  grpc (~> 1.28)
7
7
  puma (~> 4.3, >= 4.3.3)
@@ -16,9 +16,9 @@ GEM
16
16
  amatch (0.4.0)
17
17
  mize
18
18
  tins (~> 1.0)
19
- ast (2.4.0)
19
+ ast (2.4.1)
20
20
  backport (1.1.2)
21
- backports (3.17.1)
21
+ backports (3.18.1)
22
22
  benchmark (0.1.0)
23
23
  benchmark-malloc (0.2.0)
24
24
  benchmark-perf (0.6.0)
@@ -31,7 +31,7 @@ GEM
31
31
  pastel (~> 0.7)
32
32
  tty-pie (~> 0.3)
33
33
  concurrent-ruby (1.1.6)
34
- cucumber (3.1.2)
34
+ cucumber (3.2.0)
35
35
  builder (>= 2.1.2)
36
36
  cucumber-core (~> 3.2.0)
37
37
  cucumber-expressions (~> 6.0.1)
@@ -47,14 +47,14 @@ GEM
47
47
  cucumber-expressions (6.0.1)
48
48
  cucumber-tag_expressions (1.1.1)
49
49
  cucumber-wire (0.0.1)
50
- diff-lcs (1.3)
50
+ diff-lcs (1.4.4)
51
51
  docile (1.3.2)
52
52
  domain_name (0.5.20190701)
53
53
  unf (>= 0.0.5, < 1.0.0)
54
54
  e2mmap (0.1.0)
55
55
  equatable (0.6.1)
56
56
  gherkin (5.1.0)
57
- google-protobuf (3.11.4)
57
+ google-protobuf (3.12.2)
58
58
  googleapis-common-protos-types (1.0.5)
59
59
  google-protobuf (~> 3.11)
60
60
  grpc (1.28.0)
@@ -64,7 +64,7 @@ GEM
64
64
  http-accept (1.7.0)
65
65
  http-cookie (1.0.3)
66
66
  domain_name (~> 0.5)
67
- i18n (1.8.2)
67
+ i18n (1.8.3)
68
68
  concurrent-ruby (~> 1.0)
69
69
  jaro_winkler (1.5.4)
70
70
  json (2.3.0)
@@ -83,27 +83,28 @@ GEM
83
83
  nio4r (2.5.2)
84
84
  nokogiri (1.10.9)
85
85
  mini_portile2 (~> 2.4.0)
86
- parallel (1.19.1)
87
- parser (2.7.1.2)
88
- ast (~> 2.4.0)
86
+ parallel (1.19.2)
87
+ parser (2.7.1.4)
88
+ ast (~> 2.4.1)
89
89
  pastel (0.7.4)
90
90
  equatable (~> 0.6)
91
91
  tty-color (~> 0.5)
92
92
  protocol (2.0.0)
93
93
  ruby_parser (~> 3.0)
94
- puma (4.3.3)
94
+ puma (4.3.5)
95
95
  nio4r (~> 2.0)
96
- rack (2.2.2)
96
+ rack (2.2.3)
97
97
  rack-protection (2.0.8.1)
98
98
  rack
99
99
  rainbow (3.0.0)
100
100
  rake (13.0.1)
101
+ regexp_parser (1.7.1)
101
102
  rest-client (2.1.0)
102
103
  http-accept (>= 1.7.0, < 2.0)
103
104
  http-cookie (>= 1.0.2, < 2.0)
104
105
  mime-types (>= 1.16, < 4.0)
105
106
  netrc (~> 0.8)
106
- reverse_markdown (1.4.0)
107
+ reverse_markdown (2.0.0)
107
108
  nokogiri
108
109
  rexml (3.2.4)
109
110
  rspec (3.9.0)
@@ -124,18 +125,22 @@ GEM
124
125
  diff-lcs (>= 1.2.0, < 2.0)
125
126
  rspec-support (~> 3.9.0)
126
127
  rspec-support (3.9.3)
127
- rubocop (0.83.0)
128
+ rubocop (0.86.0)
128
129
  parallel (~> 1.10)
129
130
  parser (>= 2.7.0.1)
130
131
  rainbow (>= 2.2.2, < 4.0)
132
+ regexp_parser (>= 1.7)
131
133
  rexml
134
+ rubocop-ast (>= 0.0.3, < 1.0)
132
135
  ruby-progressbar (~> 1.7)
133
136
  unicode-display_width (>= 1.4.0, < 2.0)
137
+ rubocop-ast (0.1.0)
138
+ parser (>= 2.7.0.1)
134
139
  ruby-progressbar (1.10.1)
135
140
  ruby2_keywords (0.0.2)
136
141
  ruby_parser (3.14.2)
137
142
  sexp_processor (~> 4.9)
138
- sexp_processor (4.14.1)
143
+ sexp_processor (4.15.0)
139
144
  simplecov (0.17.1)
140
145
  docile (~> 1.1)
141
146
  json (>= 1.8, < 3)
@@ -146,7 +151,7 @@ GEM
146
151
  rack (~> 2.0)
147
152
  rack-protection (= 2.0.8.1)
148
153
  tilt (~> 2.0)
149
- solargraph (0.39.7)
154
+ solargraph (0.39.11)
150
155
  backport (~> 1.1)
151
156
  benchmark
152
157
  bundler (>= 1.17.2)
@@ -155,7 +160,7 @@ GEM
155
160
  maruku (~> 0.7, >= 0.7.3)
156
161
  nokogiri (~> 1.9, >= 1.9.1)
157
162
  parser (~> 2.3)
158
- reverse_markdown (~> 1.0, >= 1.0.5)
163
+ reverse_markdown (>= 1.0.5, < 3)
159
164
  rubocop (~> 0.52)
160
165
  thor (~> 1.0)
161
166
  tilt (~> 2.0)
@@ -163,7 +168,7 @@ GEM
163
168
  sync (0.5.0)
164
169
  thor (1.0.1)
165
170
  tilt (2.0.10)
166
- tins (1.24.1)
171
+ tins (1.25.0)
167
172
  sync
168
173
  tty-color (0.5.1)
169
174
  tty-cursor (0.7.1)
@@ -185,7 +190,7 @@ DEPENDENCIES
185
190
  grpc-tools (~> 1.28)
186
191
  nonnative!
187
192
  rake (~> 13.0, >= 13.0.1)
188
- rubocop (~> 0.83.0)
193
+ rubocop (~> 0.86.0)
189
194
  simplecov (~> 0.17.1)
190
195
  solargraph (~> 0.39.7)
191
196
 
data/README.md CHANGED
@@ -38,13 +38,11 @@ Configure nonnative with the following:
38
38
  - Port to verify.
39
39
  - The class for servers.
40
40
  - The file you want STDOUT to be logged to for processes.
41
- - The strategy (Startup will start the process once and before will hook into cucumbers Before and After) for processes.
41
+ - The strategy for processes/servers.
42
+ * Startup will start the process once.
43
+ * Before will hook into cucumbers Before and After.
42
44
 
43
- ### Ruby
44
-
45
- We can start a process, server or both.
46
-
47
- #### Processes
45
+ ### Processes
48
46
 
49
47
  Setup it up programmatically:
50
48
 
@@ -55,13 +53,16 @@ Nonnative.configure do |config|
55
53
  config.strategy = :startup or :before or :manual
56
54
 
57
55
  config.process do |d|
56
+ d.name = 'start_1'
58
57
  d.command = 'features/support/bin/start 12_321'
59
58
  d.timeout = 0.5
60
59
  d.port = 12_321
61
60
  d.file = 'features/logs/12_321.log'
61
+ d.signal = 'INT' # Possible values are described in Signal.list.keys
62
62
  end
63
63
 
64
64
  config.process do |d|
65
+ d.name = 'start_2'
65
66
  d.command = 'features/support/bin/start 12_322'
66
67
  d.timeout = 0.5
67
68
  d.port = 12_322
@@ -77,11 +78,14 @@ version: 1.0
77
78
  strategy: manual
78
79
  processes:
79
80
  -
81
+ name: start_1
80
82
  command: features/support/bin/start 12_321
81
83
  timeout: 5
82
84
  port: 12321
83
85
  file: features/logs/12_321.log
86
+ signal: INT # Possible values are described in Signal.list.keys
84
87
  -
88
+ name: start_2
85
89
  command: features/support/bin/start 12_322
86
90
  timeout: 5
87
91
  port: 12322
@@ -96,7 +100,7 @@ require 'nonnative'
96
100
  Nonnative.load_configuration('configuration.yml')
97
101
  ```
98
102
 
99
- #### Servers
103
+ ### Servers
100
104
 
101
105
  Define your server:
102
106
 
@@ -130,12 +134,14 @@ Nonnative.configure do |config|
130
134
  config.strategy = :manual
131
135
 
132
136
  config.server do |d|
137
+ d.name = 'server_1'
133
138
  d.klass = Nonnative::EchoServer
134
139
  d.timeout = 1
135
140
  d.port = 12_323
136
141
  end
137
142
 
138
143
  config.server do |d|
144
+ d.name = 'server_2'
139
145
  d.klass = Nonnative::EchoServer
140
146
  d.timeout = 1
141
147
  d.port = 12_324
@@ -150,10 +156,12 @@ version: 1.0
150
156
  strategy: manual
151
157
  servers:
152
158
  -
159
+ name: server_1
153
160
  klass: Nonnative::EchoServer
154
161
  timeout: 1
155
162
  port: 12323
156
163
  -
164
+ name: server_2
157
165
  klass: Nonnative::EchoServer
158
166
  timeout: 1
159
167
  port: 12324
@@ -167,26 +175,22 @@ require 'nonnative'
167
175
  Nonnative.load_configuration('configuration.yml')
168
176
  ```
169
177
 
170
- ##### HTTP
178
+ #### HTTP
171
179
 
172
180
  Define your server:
173
181
 
174
182
  ```ruby
175
183
  module Nonnative
176
184
  module Features
177
- module Hello
178
- class << self
179
- def registered(app)
180
- app.get '/hello' do
181
- 'Hello World!'
182
- end
183
- end
185
+ class Application < Sinatra::Base
186
+ get '/hello' do
187
+ 'Hello World!'
184
188
  end
185
189
  end
186
190
 
187
191
  class HTTPServer < Nonnative::HTTPServer
188
- def configure(http)
189
- http.register(Hello)
192
+ def app
193
+ Application.new
190
194
  end
191
195
  end
192
196
  end
@@ -202,6 +206,7 @@ Nonnative.configure do |config|
202
206
  config.strategy = :manual
203
207
 
204
208
  config.server do |d|
209
+ d.name = 'http_server_1'
205
210
  d.klass = Nonnative::Features::HTTPServer
206
211
  d.timeout = 1
207
212
  d.port = 4567
@@ -216,6 +221,7 @@ version: 1.0
216
221
  strategy: manual
217
222
  servers:
218
223
  -
224
+ name: http_server_1
219
225
  klass: Nonnative::Features::HTTPServer
220
226
  timeout: 1
221
227
  port: 4567
@@ -229,7 +235,7 @@ require 'nonnative'
229
235
  Nonnative.load_configuration('configuration.yml')
230
236
  ```
231
237
 
232
- ##### gRPC
238
+ #### gRPC
233
239
 
234
240
  Define your server:
235
241
 
@@ -260,6 +266,7 @@ Nonnative.configure do |config|
260
266
  config.strategy = :manual
261
267
 
262
268
  config.server do |d|
269
+ d.name = 'grpc_server_1'
263
270
  d.klass = Nonnative::Features::GRPCServer
264
271
  d.timeout = 1
265
272
  d.port = 9002
@@ -274,6 +281,7 @@ version: 1.0
274
281
  strategy: manual
275
282
  servers:
276
283
  -
284
+ name: grpc_server_1
277
285
  klass: Nonnative::Features::GRPCServer
278
286
  timeout: 1
279
287
  port: 9002
@@ -286,3 +294,35 @@ require 'nonnative'
286
294
 
287
295
  Nonnative.load_configuration('configuration.yml')
288
296
  ```
297
+ #### Proxies
298
+
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
302
+
303
+ Setup it up programmatically:
304
+
305
+ ```ruby
306
+ require 'nonnative'
307
+
308
+ Nonnative.configure do |config|
309
+ config.strategy = :manual
310
+
311
+ config.server do |d|
312
+ d.proxy.type = 'chaos'
313
+ d.proxy.port = 20_000
314
+ end
315
+ end
316
+ ```
317
+
318
+ Setup it up through configuration:
319
+
320
+ ```yaml
321
+ version: 1.0
322
+ strategy: manual
323
+ servers:
324
+ -
325
+ proxy:
326
+ type: chaos
327
+ port: 20000
328
+ ```
@@ -8,6 +8,8 @@ require 'yaml'
8
8
  require 'grpc'
9
9
  require 'sinatra'
10
10
  require 'rest-client'
11
+ require 'puma'
12
+ require 'puma/server'
11
13
 
12
14
  require 'nonnative/version'
13
15
  require 'nonnative/error'
@@ -18,6 +20,8 @@ require 'nonnative/port'
18
20
  require 'nonnative/configuration'
19
21
  require 'nonnative/configuration_process'
20
22
  require 'nonnative/configuration_server'
23
+ require 'nonnative/configuration_proxy'
24
+ require 'nonnative/service'
21
25
  require 'nonnative/command'
22
26
  require 'nonnative/pool'
23
27
  require 'nonnative/server'
@@ -26,6 +30,12 @@ require 'nonnative/http_server'
26
30
  require 'nonnative/grpc_server'
27
31
  require 'nonnative/grpc_server'
28
32
  require 'nonnative/observability'
33
+ require 'nonnative/proxy_factory'
34
+ require 'nonnative/proxy'
35
+ require 'nonnative/no_proxy'
36
+ require 'nonnative/chaos_proxy'
37
+
38
+ Thread.abort_on_exception = true
29
39
 
30
40
  module Nonnative
31
41
  class << self
@@ -38,25 +48,32 @@ module Nonnative
38
48
  end
39
49
 
40
50
  def configure
41
- yield configuration if block_given?
51
+ yield configuration
42
52
 
43
53
  require "nonnative/#{configuration.strategy}"
44
54
  end
45
55
 
46
56
  def start
47
57
  @pool ||= Nonnative::Pool.new(configuration)
58
+ errors = []
48
59
 
49
60
  @pool.start do |name, id, result|
50
- raise Nonnative::StartError, "Started #{name} with id #{id}, though did respond in time" unless result
61
+ errors << "Started #{name} with id #{id}, though did respond in time" unless result
51
62
  end
63
+
64
+ raise Nonnative::StartError, errors.join("\n") unless errors.empty?
52
65
  end
53
66
 
54
67
  def stop
55
68
  return if @pool.nil?
56
69
 
70
+ errors = []
71
+
57
72
  @pool.stop do |name, id, result|
58
- raise Nonnative::StopError, "Stopped #{name} with id #{id}, though did respond in time" unless result
73
+ errors << "Stopped #{name} with id #{id}, though did respond in time" unless result
59
74
  end
75
+
76
+ raise Nonnative::StopError, errors.join("\n") unless errors.empty?
60
77
  end
61
78
 
62
79
  def clear
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class ChaosProxy < Nonnative::Proxy
5
+ def start
6
+ @tcp_server = ::TCPServer.new('0.0.0.0', service.port)
7
+ @thread = Thread.new { perform_start }
8
+ end
9
+
10
+ def stop
11
+ thread.terminate
12
+ tcp_server.close
13
+ end
14
+
15
+ def port
16
+ service.proxy.port
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :tcp_server, :thread
22
+
23
+ def perform_start
24
+ loop do
25
+ Thread.start(tcp_server.accept) { |local_socket| connect(local_socket) }
26
+ end
27
+ end
28
+
29
+ def connect(local_socket)
30
+ remote_socket = create_remote_socket
31
+ return unless remote_socket
32
+
33
+ loop do
34
+ ready = select([local_socket, remote_socket], nil, nil)
35
+
36
+ break if write(ready, local_socket, remote_socket)
37
+ break if write(ready, remote_socket, local_socket)
38
+ end
39
+ ensure
40
+ local_socket.close
41
+ remote_socket&.close
42
+ end
43
+
44
+ def create_remote_socket
45
+ timeout.perform do
46
+ ::TCPSocket.new('0.0.0.0', port)
47
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
48
+ sleep 0.01
49
+ retry
50
+ end
51
+ end
52
+
53
+ def write(ready, socket1, socket2)
54
+ if ready[0].include?(socket1)
55
+ data = socket1.recv(1024)
56
+ return true if data.empty?
57
+
58
+ socket2.write(data)
59
+ end
60
+
61
+ false
62
+ end
63
+ end
64
+ end
@@ -1,40 +1,54 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nonnative
4
- class Command
5
- def initialize(process)
6
- @process = process
7
- @started = false
8
- end
9
-
10
- def name
11
- process.command
12
- end
13
-
4
+ class Command < Nonnative::Service
14
5
  def start
15
- unless started
16
- @pid = spawn(process.command, %i[out err] => [process.file, 'a'])
17
- @started = true
18
-
19
- sleep 0.1 # Processes take time to start
6
+ unless command_exists?
7
+ @pid = command_spawn
8
+ wait_start
20
9
  end
21
10
 
22
11
  pid
23
12
  end
24
13
 
25
14
  def stop
26
- raise Nonnative::Error, "Can't stop a process that has not started" unless started
15
+ if command_exists?
16
+ command_kill
17
+ wait_stop
18
+ end
27
19
 
28
- ::Process.kill('SIGINT', pid)
29
- @started = false
20
+ pid
21
+ end
30
22
 
31
- sleep 0.1 # Processes take time to stop
23
+ protected
32
24
 
33
- pid
25
+ def wait_stop
26
+ timeout.perform do
27
+ Process.waitpid2(pid)
28
+ end
34
29
  end
35
30
 
36
31
  private
37
32
 
38
- attr_reader :process, :pid, :started
33
+ attr_reader :pid
34
+
35
+ def command_kill
36
+ signal = Signal.list[service.signal || 'INT'] || Signal.list['INT']
37
+ Process.kill(signal, pid)
38
+ end
39
+
40
+ def command_spawn
41
+ spawn(service.command, %i[out err] => [service.file, 'a'])
42
+ end
43
+
44
+ def command_exists?
45
+ return false if pid.nil?
46
+
47
+ signal = Signal.list['EXIT']
48
+ Process.kill(signal, pid)
49
+ true
50
+ rescue Errno::ESRCH
51
+ false
52
+ end
39
53
  end
40
54
  end
@@ -20,10 +20,12 @@ module Nonnative
20
20
  processes = file['processes'] || []
21
21
  processes.each do |fd|
22
22
  config.process do |d|
23
+ d.name = fd['name']
23
24
  d.command = fd['command']
24
25
  d.timeout = fd['timeout']
25
26
  d.port = fd['port']
26
27
  d.file = fd['file']
28
+ d.signal = fd['signal']
27
29
  end
28
30
  end
29
31
  end
@@ -32,9 +34,17 @@ module Nonnative
32
34
  servers = file['servers'] || []
33
35
  servers.each do |fd|
34
36
  config.server do |s|
37
+ s.name = fd['name']
35
38
  s.klass = Object.const_get(fd['klass'])
36
39
  s.timeout = fd['timeout']
37
40
  s.port = fd['port']
41
+
42
+ proxy = fd['proxy']
43
+
44
+ if proxy
45
+ s.proxy.type = proxy['type']
46
+ s.proxy.port = proxy['port']
47
+ end
38
48
  end
39
49
  end
40
50
  end
@@ -2,9 +2,11 @@
2
2
 
3
3
  module Nonnative
4
4
  class ConfigurationProcess
5
+ attr_accessor :name
5
6
  attr_accessor :command
6
7
  attr_accessor :timeout
7
8
  attr_accessor :port
8
9
  attr_accessor :file
10
+ attr_accessor :signal
9
11
  end
10
12
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class ConfigurationProxy
5
+ attr_accessor :type
6
+ attr_accessor :port
7
+
8
+ def initialize
9
+ self.type = 'none'
10
+ self.port = 0
11
+ end
12
+ end
13
+ end
@@ -2,8 +2,14 @@
2
2
 
3
3
  module Nonnative
4
4
  class ConfigurationServer
5
+ attr_accessor :name
5
6
  attr_accessor :klass
6
7
  attr_accessor :timeout
7
8
  attr_accessor :port
9
+ attr_accessor :proxy
10
+
11
+ def initialize
12
+ self.proxy = Nonnative::ConfigurationProxy.new
13
+ end
8
14
  end
9
15
  end
@@ -2,20 +2,22 @@
2
2
 
3
3
  module Nonnative
4
4
  class GRPCServer < Nonnative::Server
5
- def initialize(port)
5
+ def initialize(service)
6
6
  @server = GRPC::RpcServer.new
7
7
 
8
- server.add_http2_port("0.0.0.0:#{port}", :this_port_is_insecure)
9
- configure server
10
-
11
- super port
8
+ super service
12
9
  end
13
10
 
14
- def configure(grpc)
11
+ def configure(server)
15
12
  # Classes will add configuration
16
13
  end
17
14
 
15
+ protected
16
+
18
17
  def perform_start
18
+ server.add_http2_port("0.0.0.0:#{proxy.port}", :this_port_is_insecure)
19
+ configure server
20
+
19
21
  server.run
20
22
  end
21
23
 
@@ -23,6 +25,18 @@ module Nonnative
23
25
  server.stop
24
26
  end
25
27
 
28
+ def wait_start
29
+ timeout.perform do
30
+ super until server.running?
31
+ end
32
+ end
33
+
34
+ def wait_stop
35
+ timeout.perform do
36
+ super until server.stopped?
37
+ end
38
+ end
39
+
26
40
  private
27
41
 
28
42
  attr_reader :server
@@ -22,6 +22,20 @@ module Nonnative
22
22
  end
23
23
  end
24
24
 
25
+ def delete(pathname, headers = {})
26
+ with_exception do
27
+ uri = URI.join(host, pathname)
28
+ RestClient.delete(uri.to_s, headers)
29
+ end
30
+ end
31
+
32
+ def put(pathname, payload, headers = {})
33
+ with_exception do
34
+ uri = URI.join(host, pathname)
35
+ RestClient.put(uri.to_s, payload.to_json, headers)
36
+ end
37
+ end
38
+
25
39
  private
26
40
 
27
41
  attr_reader :host
@@ -2,30 +2,37 @@
2
2
 
3
3
  module Nonnative
4
4
  class HTTPServer < Nonnative::Server
5
- def initialize(port)
6
- Application.set :port, port
7
- configure Application
5
+ def initialize(service)
6
+ @server = Puma::Server.new(app, Puma::Events.strings)
8
7
 
9
- super port
8
+ super service
10
9
  end
11
10
 
12
- def configure(http)
13
- # Classes will add configuration
14
- end
11
+ protected
15
12
 
16
13
  def perform_start
17
- Application.start!
14
+ server.add_tcp_listener '0.0.0.0', proxy.port
15
+ server.run.join
18
16
  end
19
17
 
20
18
  def perform_stop
21
- Application.stop!
19
+ server.stop(true)
20
+ end
21
+
22
+ def wait_start
23
+ timeout.perform do
24
+ super until server.running
25
+ end
22
26
  end
23
27
 
24
- class Application < Sinatra::Application
25
- set :bind, '0.0.0.0'
26
- set :server, :puma
27
- set :logging, false
28
- set :quiet, true
28
+ def wait_stop
29
+ timeout.perform do
30
+ super while server.running
31
+ end
29
32
  end
33
+
34
+ private
35
+
36
+ attr_reader :queue, :server
30
37
  end
31
38
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class NoProxy < Proxy
5
+ def start
6
+ # Do nothing.
7
+ end
8
+
9
+ def stop
10
+ # Do nothing.
11
+ end
12
+
13
+ def port
14
+ service.port
15
+ end
16
+ end
17
+ end
@@ -28,7 +28,7 @@ module Nonnative
28
28
 
29
29
  def servers
30
30
  @servers ||= configuration.servers.map do |d|
31
- [d.klass.new(d.port), Nonnative::Port.new(d)]
31
+ [d.klass.new(d), Nonnative::Port.new(d)]
32
32
  end
33
33
  end
34
34
 
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class Proxy
5
+ def initialize(service)
6
+ @service = service
7
+ @timeout = Nonnative::Timeout.new(service.timeout)
8
+ end
9
+
10
+ protected
11
+
12
+ attr_reader :service, :timeout
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class ProxyFactory
5
+ class << self
6
+ def create(service)
7
+ case service.proxy.type
8
+ when 'chaos'
9
+ ChaosProxy.new(service)
10
+ else
11
+ # By default we want no proxy.
12
+ NoProxy.new(service)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,34 +1,44 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nonnative
4
- class Server < Thread
5
- def initialize(port)
6
- @port = port
7
- self.abort_on_exception = true
4
+ class Server < Nonnative::Service
5
+ def initialize(service)
6
+ @id = SecureRandom.hex(5)
7
+ @proxy = Nonnative::ProxyFactory.create(service)
8
8
 
9
- super do
10
- perform_start
11
- end
12
- end
13
-
14
- def name
15
- self.class.to_s
9
+ super service
16
10
  end
17
11
 
18
12
  def start
19
- sleep 0.1 # Servers take time to start
13
+ unless thread
14
+ proxy.start
15
+ @thread = Thread.new { perform_start }
16
+
17
+ wait_start
18
+ end
20
19
 
21
- object_id
20
+ id
22
21
  end
23
22
 
24
23
  def stop
25
- perform_stop
24
+ if thread
25
+ perform_stop
26
+ thread.terminate
27
+ proxy.stop
26
28
 
27
- sleep 0.1 # Servers take time to stop
29
+ @thread = nil
30
+ wait_stop
31
+ end
28
32
 
29
- object_id
33
+ id
30
34
  end
31
35
 
32
- attr_reader :port
36
+ protected
37
+
38
+ attr_reader :id
39
+
40
+ private
41
+
42
+ attr_reader :proxy, :thread
33
43
  end
34
44
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class Service
5
+ def initialize(service)
6
+ @service = service
7
+ @timeout = Nonnative::Timeout.new(service.timeout)
8
+ end
9
+
10
+ def name
11
+ service.name
12
+ end
13
+
14
+ protected
15
+
16
+ attr_reader :service, :timeout
17
+
18
+ def wait_start
19
+ sleep 0.1
20
+ end
21
+
22
+ def wait_stop
23
+ sleep 0.1
24
+ end
25
+ end
26
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- Nonnative.start
4
-
5
3
  at_exit do
6
4
  Nonnative.stop
7
5
  end
6
+
7
+ Nonnative.start
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nonnative
4
- VERSION = '1.11.0'
4
+ VERSION = '1.16.0'
5
5
  end
@@ -36,7 +36,7 @@ Gem::Specification.new do |spec|
36
36
  spec.add_development_dependency 'chutney', '~> 2.0', '>= 2.0.3.1'
37
37
  spec.add_development_dependency 'grpc-tools', '~> 1.28'
38
38
  spec.add_development_dependency 'rake', '~> 13.0', '>= 13.0.1'
39
- spec.add_development_dependency 'rubocop', '~> 0.83.0'
39
+ spec.add_development_dependency 'rubocop', '~> 0.86.0'
40
40
  spec.add_development_dependency 'simplecov', '~> 0.17.1'
41
41
  spec.add_development_dependency 'solargraph', '~> 0.39.7'
42
42
  end
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.11.0
4
+ version: 1.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Falkowski
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-14 00:00:00.000000000 Z
11
+ date: 2020-07-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cucumber
@@ -212,14 +212,14 @@ dependencies:
212
212
  requirements:
213
213
  - - "~>"
214
214
  - !ruby/object:Gem::Version
215
- version: 0.83.0
215
+ version: 0.86.0
216
216
  type: :development
217
217
  prerelease: false
218
218
  version_requirements: !ruby/object:Gem::Requirement
219
219
  requirements:
220
220
  - - "~>"
221
221
  - !ruby/object:Gem::Version
222
- version: 0.83.0
222
+ version: 0.86.0
223
223
  - !ruby/object:Gem::Dependency
224
224
  name: simplecov
225
225
  requirement: !ruby/object:Gem::Requirement
@@ -271,19 +271,25 @@ files:
271
271
  - bin/setup
272
272
  - lib/nonnative.rb
273
273
  - lib/nonnative/before.rb
274
+ - lib/nonnative/chaos_proxy.rb
274
275
  - lib/nonnative/command.rb
275
276
  - lib/nonnative/configuration.rb
276
277
  - lib/nonnative/configuration_process.rb
278
+ - lib/nonnative/configuration_proxy.rb
277
279
  - lib/nonnative/configuration_server.rb
278
280
  - lib/nonnative/error.rb
279
281
  - lib/nonnative/grpc_server.rb
280
282
  - lib/nonnative/http_client.rb
281
283
  - lib/nonnative/http_server.rb
282
284
  - lib/nonnative/manual.rb
285
+ - lib/nonnative/no_proxy.rb
283
286
  - lib/nonnative/observability.rb
284
287
  - lib/nonnative/pool.rb
285
288
  - lib/nonnative/port.rb
289
+ - lib/nonnative/proxy.rb
290
+ - lib/nonnative/proxy_factory.rb
286
291
  - lib/nonnative/server.rb
292
+ - lib/nonnative/service.rb
287
293
  - lib/nonnative/start_error.rb
288
294
  - lib/nonnative/startup.rb
289
295
  - lib/nonnative/stop_error.rb
@@ -310,7 +316,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
310
316
  - !ruby/object:Gem::Version
311
317
  version: '0'
312
318
  requirements: []
313
- rubygems_version: 3.0.3
319
+ rubygems_version: 3.0.8
314
320
  signing_key:
315
321
  specification_version: 4
316
322
  summary: Allows you to keep using the power of ruby to test other systems