nonnative 2.16.0 → 2.19.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9b79bc3b75303cd4d605a4ef81c7b3c1eedd188204d088864fefb65dc73f0922
4
- data.tar.gz: c8e4b5ef1bb12213e80d7084d5b3809206279a44bca610947114fd41dd188745
3
+ metadata.gz: '08e1e5b760ed902c52e55ef0694bddeb1e36580891ab9a778767a04ea02b1d9c'
4
+ data.tar.gz: d632a3b8047ebada176e3db071caada192b87d8c255d6beb0e14a1010874103f
5
5
  SHA512:
6
- metadata.gz: a58c635d40b6eeb8b6aa7e9560900bad247fe768f9839b7e141f6be4e500b5fa2ec11267524621db66989f6eaf24601b790716a4508e28203e4845862ad5a289
7
- data.tar.gz: 111995ab26c566d24df0fb037c094883ac07adf2142254fde6822fb9e4fcea59c855196c650bac382e5ab02fe2610181611040a96f3d13515aef586495ffaf72
6
+ metadata.gz: bfeba487e42d817e967c0a1cfe0814e5fc75c4d360399dcbd0caaf6ddef83c11efb8a4aff8ffe58ee6566be138b3b85e146e5ffe44dc431e734cf22544956019
7
+ data.tar.gz: 268c3d360f3d23b18a69317cbe656b06d24b8f94799c245108e94e5e269ac852c000d74d3427168fd2ad5b2c56ea24a3bb21e1507c77d9e4cce713fac4b57a3b
data/.circleci/config.yml CHANGED
@@ -3,7 +3,7 @@ version: 2.1
3
3
  jobs:
4
4
  build:
5
5
  docker:
6
- - image: alexfalkowski/ruby:3.8
6
+ - image: alexfalkowski/ruby:3.9
7
7
  working_directory: ~/nonnative
8
8
  steps:
9
9
  - checkout:
@@ -58,7 +58,7 @@ jobs:
58
58
  resource_class: arm.large
59
59
  wait-all:
60
60
  docker:
61
- - image: alexfalkowski/ruby:3.8
61
+ - image: alexfalkowski/ruby:3.9
62
62
  steps:
63
63
  - run: echo "all applicable jobs finished"
64
64
  resource_class: arm.large
data/AGENTS.md CHANGED
@@ -79,6 +79,9 @@ Fault-injection states: `none`, `close_all`, `delay`, `invalid_data`.
79
79
 
80
80
  Config rules:
81
81
 
82
+ - YAML config is loaded as data only via `Nonnative::ConfigurationFile`; ERB is not evaluated and arbitrary Ruby object tags are rejected
83
+ - Runner `host` and nested `proxy.host` default to `127.0.0.1`; use explicit `0.0.0.0` only when external access is intended
84
+ - Process `command` can be a legacy shell string or an argv array; prefer argv arrays for new config, and `go:` config builds argv internally
82
85
  - YAML services belong under `services:`, not `processes:`
83
86
  - There is no top-level `config.wait`; `wait` is per runner
84
87
  - Programmatic service config uses `config.service do |s| ... end`, so use `s.host` / `s.port`
@@ -107,4 +110,4 @@ Limitations:
107
110
  - Process lifecycle: `lib/nonnative/process.rb`
108
111
  - Proxies: `lib/nonnative/fault_injection_proxy.rb`, `lib/nonnative/socket_pair_factory.rb`
109
112
  - Cucumber: `lib/nonnative/cucumber.rb`, `lib/nonnative/startup.rb`, `features/support/env.rb`
110
- - Config loading: `lib/nonnative/configuration.rb`, `lib/nonnative/configuration_runner.rb`, `lib/nonnative/configuration_proxy.rb`
113
+ - Config loading: `lib/nonnative/configuration.rb`, `lib/nonnative/configuration_file.rb`, `lib/nonnative/configuration_runner.rb`, `lib/nonnative/configuration_proxy.rb`
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nonnative (2.16.0)
4
+ nonnative (2.19.1)
5
5
  concurrent-ruby (>= 1, < 2)
6
6
  config (>= 5, < 6)
7
7
  cucumber (>= 7, < 12)
data/README.md CHANGED
@@ -37,7 +37,9 @@ gem install nonnative
37
37
 
38
38
  ## Usage
39
39
 
40
- Nonnative is configured via {#Nonnative.configure} (programmatic) or `config.load_file(...)` (YAML).
40
+ Nonnative is configured via `Nonnative.configure` (programmatic) or `config.load_file(...)` (YAML).
41
+ YAML configuration is loaded as data only: ERB is not evaluated and arbitrary Ruby objects are not
42
+ deserialized.
41
43
 
42
44
  High-level configuration fields:
43
45
  - `version`: configuration version (example: `"1.0"`).
@@ -48,13 +50,16 @@ High-level configuration fields:
48
50
  - `servers`: in-process Ruby servers started in threads.
49
51
  - `services`: external dependencies (proxy-only; no process/thread started by Nonnative).
50
52
 
51
- Runner fields (process/server/service):
53
+ Common runner fields:
54
+ - `name`: runner name used for lookup.
55
+ - `host`/`port`: client-facing address. `host` defaults to `127.0.0.1`. For processes and servers, this address is also used for readiness/shutdown port checks. When a `fault_injection` proxy is enabled, this is the endpoint your tests/clients should hit.
56
+
57
+ Process/server fields:
52
58
  - `timeout`: max time (seconds) for readiness/shutdown port checks.
53
59
  - `wait`: small sleep (seconds) between lifecycle steps.
54
- - `host`/`port`: client-facing address used for readiness/shutdown port checks. When a `fault_injection` proxy is enabled, this is the endpoint your tests/clients should hit.
55
- - `log`: per-runner log file (used by process output redirection or server implementations).
60
+ - `log`: per-runner log file used by process output redirection or server implementations.
56
61
 
57
- For `fault_injection`, the nested `proxy.host`/`proxy.port` describe the upstream target behind the proxy. In-process server implementations typically bind there via `proxy.host` / `proxy.port`.
62
+ For `fault_injection`, the nested `proxy.host`/`proxy.port` describe the upstream target behind the proxy. Nested `proxy.host` also defaults to `127.0.0.1`. In-process server implementations typically bind there via `proxy.host` / `proxy.port`.
58
63
 
59
64
  Nonnative readiness and shutdown checks are TCP-only. Configure ports that are dedicated to the test run; if another process is already listening on the same `host`/`port`, results are undefined.
60
65
 
@@ -90,8 +95,10 @@ This calls `Nonnative.start` immediately and registers an `at_exit` stop.
90
95
  ### Processes
91
96
 
92
97
  A process is some sort of command that you would run locally.
98
+ Commands can be strings or argv arrays. String commands preserve legacy shell semantics, while argv arrays
99
+ avoid shell interpretation and are preferred for new configuration.
93
100
 
94
- Setup it up programmatically:
101
+ Set it up programmatically:
95
102
 
96
103
  ```ruby
97
104
  require 'nonnative'
@@ -104,7 +111,7 @@ Nonnative.configure do |config|
104
111
 
105
112
  config.process do |p|
106
113
  p.name = 'start_1'
107
- p.command = -> { 'features/support/bin/start 12_321' }
114
+ p.command = -> { ['features/support/bin/start', '12_321'] }
108
115
  p.timeout = 5
109
116
  p.wait = 0.1
110
117
  p.port = 12_321
@@ -117,7 +124,7 @@ Nonnative.configure do |config|
117
124
 
118
125
  config.process do |p|
119
126
  p.name = 'start_2'
120
- p.command = -> { 'features/support/bin/start 12_322' }
127
+ p.command = -> { ['features/support/bin/start', '12_322'] }
121
128
  p.timeout = 0.5
122
129
  p.wait = 0.1
123
130
  p.port = 12_322
@@ -126,7 +133,7 @@ Nonnative.configure do |config|
126
133
  end
127
134
  ```
128
135
 
129
- Setup it up through configuration:
136
+ Set it up through configuration:
130
137
 
131
138
  ```yaml
132
139
  version: "1.0"
@@ -136,7 +143,9 @@ log: nonnative.log
136
143
  processes:
137
144
  -
138
145
  name: start_1
139
- command: features/support/bin/start 12_321
146
+ command:
147
+ - features/support/bin/start
148
+ - "12_321"
140
149
  timeout: 5
141
150
  wait: 1
142
151
  port: 12321
@@ -146,7 +155,9 @@ processes:
146
155
  TEST: true
147
156
  -
148
157
  name: start_2
149
- command: features/support/bin/start 12_322
158
+ command:
159
+ - features/support/bin/start
160
+ - "12_322"
150
161
  timeout: 5
151
162
  wait: 1
152
163
  port: 12322
@@ -205,7 +216,7 @@ module Nonnative
205
216
  end
206
217
  ```
207
218
 
208
- Setup it up programmatically:
219
+ Set it up programmatically:
209
220
 
210
221
  ```ruby
211
222
  require 'nonnative'
@@ -218,7 +229,7 @@ Nonnative.configure do |config|
218
229
 
219
230
  config.server do |s|
220
231
  s.name = 'server_1'
221
- s.klass = Nonnative::EchoServer
232
+ s.klass = Nonnative::TCPServer
222
233
  s.timeout = 1
223
234
  s.port = 12_323
224
235
  s.log = 'server_1.log'
@@ -226,7 +237,7 @@ Nonnative.configure do |config|
226
237
 
227
238
  config.server do |s|
228
239
  s.name = 'server_2'
229
- s.klass = Nonnative::EchoServer
240
+ s.klass = Nonnative::TCPServer
230
241
  s.timeout = 1
231
242
  s.port = 12_324
232
243
  s.log = 'server_2.log'
@@ -234,7 +245,7 @@ Nonnative.configure do |config|
234
245
  end
235
246
  ```
236
247
 
237
- Setup it up through configuration:
248
+ Set it up through configuration:
238
249
 
239
250
  ```yaml
240
251
  version: "1.0"
@@ -244,13 +255,13 @@ log: nonnative.log
244
255
  servers:
245
256
  -
246
257
  name: server_1
247
- class: Nonnative::EchoServer
258
+ class: Nonnative::TCPServer
248
259
  timeout: 1
249
260
  port: 12323
250
261
  log: server_1.log
251
262
  -
252
263
  name: server_2
253
- class: Nonnative::EchoServer
264
+ class: Nonnative::TCPServer
254
265
  timeout: 1
255
266
  port: 12324
256
267
  log: server_2.log
@@ -288,7 +299,7 @@ module Nonnative
288
299
  end
289
300
  ```
290
301
 
291
- Setup it up programmatically:
302
+ Set it up programmatically:
292
303
 
293
304
  ```ruby
294
305
  require 'nonnative'
@@ -309,7 +320,7 @@ Nonnative.configure do |config|
309
320
  end
310
321
  ```
311
322
 
312
- Setup it up through configuration:
323
+ Set it up through configuration:
313
324
 
314
325
  ```yaml
315
326
  version: "1.0"
@@ -353,7 +364,7 @@ module Nonnative
353
364
  end
354
365
  ```
355
366
 
356
- Setup it up programmatically:
367
+ Set it up programmatically:
357
368
 
358
369
  ```ruby
359
370
  require 'nonnative'
@@ -374,7 +385,7 @@ Nonnative.configure do |config|
374
385
  end
375
386
  ```
376
387
 
377
- Setup it up through configuration:
388
+ Set it up through configuration:
378
389
 
379
390
  ```yaml
380
391
  version: "1.0"
@@ -422,7 +433,7 @@ module Nonnative
422
433
  end
423
434
  ```
424
435
 
425
- Setup it up programmatically:
436
+ Set it up programmatically:
426
437
 
427
438
  ```ruby
428
439
  require 'nonnative'
@@ -443,7 +454,7 @@ Nonnative.configure do |config|
443
454
  end
444
455
  ```
445
456
 
446
- Setup it up through configuration:
457
+ Set it up through configuration:
447
458
 
448
459
  ```yaml
449
460
  version: "1.0"
@@ -705,7 +716,7 @@ Clients connect to the runner `host`/`port`, while the proxy forwards traffic to
705
716
 
706
717
  ###### Fault Injection Processes
707
718
 
708
- Setup it up programmatically:
719
+ Set it up programmatically:
709
720
 
710
721
  ```ruby
711
722
  name = 'name of process in configuration'
@@ -724,7 +735,7 @@ Then I should reset the proxy for process 'process_1'
724
735
 
725
736
  ###### Fault Injection Servers
726
737
 
727
- Setup it up programmatically:
738
+ Set it up programmatically:
728
739
 
729
740
  ```ruby
730
741
  name = 'name of server in configuration'
@@ -743,7 +754,7 @@ Then I should reset the proxy for server 'server_1'
743
754
 
744
755
  ###### Fault Injection Services
745
756
 
746
- Setup it up programmatically:
757
+ Set it up programmatically:
747
758
 
748
759
  ```ruby
749
760
  name = 'name of service in configuration'
@@ -762,11 +773,26 @@ Then I should reset the proxy for service 'service_1'
762
773
 
763
774
  ### Go
764
775
 
765
- As we love using go as a language for services we have added support to start binaries with defined parameters. This expects that you build your services in the format of `command sub_command --params`
776
+ As we love using Go as a language for services we have added support to start binaries with defined parameters.
777
+
778
+ Programmatic Go binaries can be configured as normal argv process commands:
779
+
780
+ ```ruby
781
+ Nonnative.configure do |config|
782
+ config.process do |p|
783
+ p.name = 'go'
784
+ p.command = -> { ['your_binary', 'sub_command', '--config', 'config.yaml'] }
785
+ p.port = 12_345
786
+ end
787
+ end
788
+ ```
789
+
790
+ YAML `go:` configuration is for Go test binaries compiled with `go test -c`. It builds argv entries in this order: executable, optional `-test.*` profiling/trace/coverage flags, command, then parameters. Parameter strings are parsed into argv words with shell-style quoting, but the argv entries are executed without shell interpretation.
766
791
 
767
792
  To get this to work you will need to create a `main_test.go` file with these contents:
768
793
 
769
794
  ```go
795
+ //go:build features
770
796
  // +build features
771
797
 
772
798
  package main
@@ -774,7 +800,7 @@ package main
774
800
  import "testing"
775
801
 
776
802
  func TestFeatures(t *testing.T) {
777
- main()
803
+ main()
778
804
  }
779
805
  ```
780
806
 
@@ -784,15 +810,7 @@ Then to compile this binary you will need to do the following:
784
810
  go test -mod vendor -c -tags features -covermode=count -o your_binary -coverpkg=./... github.com/your_location
785
811
  ```
786
812
 
787
- Setup it up programmatically:
788
-
789
- ```ruby
790
- tools = %w[prof trace cover]
791
-
792
- Nonnative.go_executable(tools, 'reports', 'your_binary', 'sub_command', '--config config.yaml')
793
- ```
794
-
795
- Setup it up through configuration:
813
+ Set it up through configuration:
796
814
 
797
815
  ```yaml
798
816
  version: "1.0"
@@ -808,7 +826,7 @@ processes:
808
826
  executable: your_binary
809
827
  command: sub_command
810
828
  parameters:
811
- - --config config.yaml
829
+ - "-i file:.config/server.yml"
812
830
  timeout: 5
813
831
  port: 8000
814
832
  log: go.log
@@ -52,13 +52,14 @@ module Nonnative
52
52
 
53
53
  # Loads a configuration file and appends its runners to this instance.
54
54
  #
55
- # The file is loaded using the `config` gem via {Nonnative.configurations}. Top-level attributes are
56
- # copied onto this object, and runner sections are transformed into configuration runner objects.
55
+ # The file is loaded using safe YAML parsing. ERB is not evaluated,
56
+ # arbitrary object deserialization is not allowed, top-level attributes are copied onto this object,
57
+ # and runner sections are transformed into configuration runner objects.
57
58
  #
58
59
  # @param path [String] path to a configuration file (typically YAML)
59
60
  # @return [void]
60
61
  def load_file(path)
61
- cfg = Nonnative.configurations(path)
62
+ cfg = Nonnative::ConfigurationFile.load(path)
62
63
 
63
64
  self.version = cfg.version
64
65
  self.name = cfg.name
@@ -140,7 +141,7 @@ module Nonnative
140
141
  params = go.parameters || []
141
142
  tools = go.tools || []
142
143
 
143
- -> { Nonnative.go_executable(tools, go.output, go.executable, go.command, *params) }
144
+ -> { Nonnative.go_executable_args(tools, go.output, go.executable, go.command, *params) }
144
145
  else
145
146
  -> { process.command }
146
147
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ # Safely loads a YAML configuration file into the Config::Options shape used by Nonnative.
5
+ class ConfigurationFile
6
+ class << self
7
+ # Loads a file into a Config::Options instance.
8
+ #
9
+ # YAML files are parsed as data only: ERB is not evaluated and arbitrary object deserialization is not allowed.
10
+ #
11
+ # @param path [String] file path
12
+ # @return [Config::Options]
13
+ def load(path)
14
+ Config::Options.new.tap do |config|
15
+ config.add_source!(safe_load_yaml(path))
16
+ config.load!
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def safe_load_yaml(path)
23
+ contents = File.read(path)
24
+ config = YAML.safe_load(contents, aliases: true) || {}
25
+ return config if config.is_a?(Hash)
26
+
27
+ raise ArgumentError, "Configuration file '#{path}' must contain a YAML mapping"
28
+ rescue Psych::SyntaxError => e
29
+ raise ArgumentError, "YAML syntax error occurred while parsing #{path}: #{e.message}"
30
+ end
31
+ end
32
+ end
33
+ end
@@ -11,11 +11,21 @@ module Nonnative
11
11
  # @see Nonnative::Configuration
12
12
  # @see Nonnative::Process
13
13
  class ConfigurationProcess < ConfigurationRunner
14
- # @return [Proc] a callable that returns the command string to execute (e.g. `-> { "./bin/api" }`)
14
+ # @return [Proc] a callable that returns the command to execute
15
+ # as a shell string or argv array
16
+ # (e.g. `-> { "./bin/api" }` or `-> { ["./bin/api", "--port", "8080"] }`)
17
+ attr_accessor :command
18
+
15
19
  # @return [String, nil] signal name to use for stopping (defaults to `"INT"` when not set)
20
+ attr_accessor :signal
21
+
16
22
  # @return [Numeric] readiness timeout (seconds) used when waiting for the port to open/close
23
+ attr_accessor :timeout
24
+
17
25
  # @return [String] log file path to append process stdout/stderr to
26
+ attr_accessor :log
27
+
18
28
  # @return [Hash, nil] environment variables to pass to the spawned process
19
- attr_accessor :command, :signal, :timeout, :log, :environment
29
+ attr_accessor :environment
20
30
  end
21
31
  end
@@ -15,7 +15,7 @@ module Nonnative
15
15
  # @see Nonnative.proxies
16
16
  class ConfigurationProxy
17
17
  # @return [String] proxy kind name (for example `"none"` or `"fault_injection"`)
18
- # @return [String] upstream host used by proxy implementations (defaults to `"0.0.0.0"`)
18
+ # @return [String] upstream host used by proxy implementations (defaults to `"127.0.0.1"`)
19
19
  # @return [Integer] upstream port used by proxy implementations (defaults to `0`)
20
20
  # @return [String, nil] path to proxy log file (implementation-dependent)
21
21
  # @return [Numeric] wait interval (seconds) after proxy state changes (defaults to `0.1`)
@@ -27,7 +27,7 @@ module Nonnative
27
27
  #
28
28
  # Defaults:
29
29
  # - `kind`: `"none"`
30
- # - `host`: `"0.0.0.0"`
30
+ # - `host`: `"127.0.0.1"`
31
31
  # - `port`: `0`
32
32
  # - `wait`: `0.1`
33
33
  # - `options`: `{}`
@@ -35,7 +35,7 @@ module Nonnative
35
35
  # @return [void]
36
36
  def initialize
37
37
  self.kind = 'none'
38
- self.host = '0.0.0.0'
38
+ self.host = '127.0.0.1'
39
39
  self.port = 0
40
40
  self.wait = 0.1
41
41
  self.options = {}
@@ -14,7 +14,7 @@ module Nonnative
14
14
  # @see Nonnative::ConfigurationService
15
15
  class ConfigurationRunner
16
16
  # @return [String, nil] runner name used for lookup (for example via `pool.process_by_name`)
17
- # @return [String] host to bind/connect to (defaults to `"0.0.0.0"`)
17
+ # @return [String] host to bind/connect to (defaults to `"127.0.0.1"`)
18
18
  # @return [Integer] port to bind/connect to
19
19
  # @return [Numeric] wait interval (seconds) used by runners between lifecycle steps
20
20
  attr_accessor :name, :host, :port, :wait
@@ -30,14 +30,14 @@ module Nonnative
30
30
  # Creates a runner configuration with defaults.
31
31
  #
32
32
  # Defaults:
33
- # - `host`: `"0.0.0.0"`
33
+ # - `host`: `"127.0.0.1"`
34
34
  # - `port`: `0`
35
35
  # - `wait`: `0.1`
36
36
  # - `proxy`: a new {Nonnative::ConfigurationProxy} with its own defaults
37
37
  #
38
38
  # @return [void]
39
39
  def initialize
40
- self.host = '0.0.0.0'
40
+ self.host = '127.0.0.1'
41
41
  self.port = 0
42
42
  self.wait = 0.1
43
43
 
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nonnative
4
- # Builds command lines for running a Go test binary with optional profiling/trace/coverage flags.
4
+ # Builds commands for running a Go test binary with optional profiling/trace/coverage flags.
5
5
  #
6
- # This helper is used by {Nonnative.go_executable} and by YAML configuration when a process has a
7
- # `go:` section (see {Nonnative::Configuration}).
6
+ # This helper is used by YAML configuration when a process has a `go:` section
7
+ # (see {Nonnative::Configuration}).
8
8
  #
9
9
  # The generated flags use Go's `testing` package flags (e.g. `-test.cpuprofile=...`), so this
10
10
  # is intended to run a binary compiled from `go test -c`.
@@ -19,12 +19,14 @@ module Nonnative
19
19
  #
20
20
  # If `tools` is `nil` or empty, all tools (`prof`, `trace`, `cover`) are enabled.
21
21
  #
22
+ # Parameter strings are parsed into argv words using shell-style quoting, then executed without a shell.
23
+ #
22
24
  # @example
23
25
  # cmd = Nonnative::GoCommand.new(%w[prof cover], './svc.test', 'reports')
24
- # cmd.executable('serve', '--config', 'config.yaml')
25
- # # => "./svc.test -test.cpuprofile=... -test.coverprofile=... serve --config config.yaml"
26
+ # cmd.executable_args('serve', '--config', 'config.yaml')
27
+ # # => ["./svc.test", "-test.cpuprofile=...", "-test.coverprofile=...", "serve", "--config", "config.yaml"]
26
28
  #
27
- # @see Nonnative.go_executable
29
+ # @see Nonnative.go_executable_args
28
30
  class GoCommand
29
31
  # @param tools [Array<String>, nil] tool names to enable (see class docs)
30
32
  # @param exec [String] path to the compiled Go test binary
@@ -35,22 +37,25 @@ module Nonnative
35
37
  @output = output
36
38
  end
37
39
 
38
- # Returns an executable command string including enabled `-test.*` flags.
40
+ # Returns an executable argv array including enabled `-test.*` flags.
39
41
  #
40
42
  # A short random suffix is appended to output filenames to reduce collisions across runs.
41
43
  #
42
44
  # @param cmd [String] command/sub-command argument passed to the Go test binary
43
- # @param params [Array<String>] additional parameters passed after `cmd`
44
- # @return [String] the full command to execute
45
- def executable(cmd, *params)
46
- params = params.join(' ')
47
- "#{exec} #{flags(cmd).join(' ')} #{cmd} #{params}".strip
45
+ # @param params [Array<String>] additional parameter strings passed after `cmd`
46
+ # @return [Array<String>] argv entries to execute
47
+ def executable_args(cmd, *params)
48
+ [exec, *flags(cmd), cmd, *parameter_args(params)]
48
49
  end
49
50
 
50
51
  private
51
52
 
52
53
  attr_reader :tools, :exec, :output
53
54
 
55
+ def parameter_args(params)
56
+ params.flatten.compact.flat_map { |p| Shellwords.split(p.to_s) }
57
+ end
58
+
54
59
  def flags(cmd)
55
60
  suffix = SecureRandom.alphanumeric(4)
56
61
  m = File.basename(exec, File.extname(exec))
@@ -89,10 +89,10 @@ module Nonnative
89
89
  environment[k] = ENV.fetch(k, nil) || environment[k]
90
90
  end
91
91
 
92
- command = service.command.call
92
+ command = Array(service.command.call)
93
93
 
94
- spawn(environment, command, %i[out err] => [service.log, 'a']).tap do |pid|
95
- Nonnative.logger.info "started '#{command}' with pid '#{pid}'"
94
+ spawn(environment, *command, %i[out err] => [service.log, 'a']).tap do |pid|
95
+ Nonnative.logger.info "started '#{command.join(' ')}' with pid '#{pid}'"
96
96
  end
97
97
  end
98
98
 
@@ -4,5 +4,5 @@ module Nonnative
4
4
  # The current gem version.
5
5
  #
6
6
  # @return [String]
7
- VERSION = '2.16.0'
7
+ VERSION = '2.19.1'
8
8
  end
data/lib/nonnative.rb CHANGED
@@ -46,6 +46,7 @@ require 'timeout'
46
46
  require 'yaml'
47
47
  require 'open3'
48
48
  require 'securerandom'
49
+ require 'shellwords'
49
50
 
50
51
  require 'grpc'
51
52
  require 'sinatra'
@@ -67,6 +68,7 @@ require 'nonnative/stop_error'
67
68
  require 'nonnative/not_found_error'
68
69
  require 'nonnative/timeout'
69
70
  require 'nonnative/port'
71
+ require 'nonnative/configuration_file'
70
72
  require 'nonnative/configuration'
71
73
  require 'nonnative/configuration_runner'
72
74
  require 'nonnative/configuration_process'
@@ -113,16 +115,6 @@ module Nonnative
113
115
  # @return [Nonnative::Pool, nil] the pool instance, or `nil` if not started yet
114
116
  attr_accessor :pool
115
117
 
116
- # Loads one or more configuration files using the `config` gem.
117
- #
118
- # This is primarily used by {Nonnative::Configuration#load_file}, but is public for advanced cases.
119
- #
120
- # @param files [Array<String>] paths to configuration files
121
- # @return [Config::Options] the loaded configuration object
122
- def configurations(*files)
123
- Config.load_files(files)
124
- end
125
-
126
118
  # Returns the current configuration (memoized).
127
119
  #
128
120
  # @return [Nonnative::Configuration]
@@ -162,7 +154,7 @@ module Nonnative
162
154
  File.readlines(path).select { |l| predicate.call(l) }
163
155
  end
164
156
 
165
- # Builds a Go test executable command line with optional profiling/trace/coverage flags.
157
+ # Builds a Go test executable argv array with optional profiling/trace/coverage flags.
166
158
  #
167
159
  # This is used when process configuration specifies a `go` section.
168
160
  #
@@ -170,10 +162,10 @@ module Nonnative
170
162
  # @param output [String] directory where outputs should be written
171
163
  # @param exec [String] the test binary (or wrapper) to execute
172
164
  # @param cmd [String] the command argument passed to the test binary
173
- # @param params [Array<String>] extra parameters for the command
174
- # @return [String] executable command string
175
- def go_executable(tools, output, exec, cmd, *params)
176
- Nonnative::GoCommand.new(tools, exec, output).executable(cmd, params)
165
+ # @param params [Array<String>] extra parameter strings for the command
166
+ # @return [Array<String>] executable argv entries
167
+ def go_executable_args(tools, output, exec, cmd, *params)
168
+ Nonnative::GoCommand.new(tools, exec, output).executable_args(cmd, *params)
177
169
  end
178
170
 
179
171
  # Returns an HTTP client for common health/readiness endpoints.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nonnative
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.16.0
4
+ version: 2.19.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alejandro Falkowski
@@ -288,6 +288,7 @@ files:
288
288
  - lib/nonnative.rb
289
289
  - lib/nonnative/close_all_socket_pair.rb
290
290
  - lib/nonnative/configuration.rb
291
+ - lib/nonnative/configuration_file.rb
291
292
  - lib/nonnative/configuration_process.rb
292
293
  - lib/nonnative/configuration_proxy.rb
293
294
  - lib/nonnative/configuration_runner.rb