Module: Nonnative

Defined in:
lib/nonnative.rb,
lib/nonnative/pool.rb,
lib/nonnative/port.rb,
lib/nonnative/error.rb,
lib/nonnative/ports.rb,
lib/nonnative/proxy.rb,
lib/nonnative/header.rb,
lib/nonnative/runner.rb,
lib/nonnative/server.rb,
lib/nonnative/process.rb,
lib/nonnative/service.rb,
lib/nonnative/timeout.rb,
lib/nonnative/version.rb,
lib/nonnative/cucumber.rb,
lib/nonnative/no_proxy.rb,
lib/nonnative/tcp_probe.rb,
lib/nonnative/grpc_probe.rb,
lib/nonnative/http_probe.rb,
lib/nonnative/stop_error.rb,
lib/nonnative/grpc_health.rb,
lib/nonnative/grpc_server.rb,
lib/nonnative/http_client.rb,
lib/nonnative/http_server.rb,
lib/nonnative/socket_pair.rb,
lib/nonnative/start_error.rb,
lib/nonnative/configuration.rb,
lib/nonnative/go_executable.rb,
lib/nonnative/observability.rb,
lib/nonnative/proxy_factory.rb,
lib/nonnative/not_found_error.rb,
lib/nonnative/delay_socket_pair.rb,
lib/nonnative/http_proxy_server.rb,
lib/nonnative/configuration_file.rb,
lib/nonnative/configuration_proxy.rb,
lib/nonnative/socket_pair_factory.rb,
lib/nonnative/configuration_runner.rb,
lib/nonnative/configuration_server.rb,
lib/nonnative/close_all_socket_pair.rb,
lib/nonnative/configuration_process.rb,
lib/nonnative/configuration_service.rb,
lib/nonnative/fault_injection_proxy.rb,
lib/nonnative/configuration_readiness.rb,
lib/nonnative/invalid_data_socket_pair.rb,
lib/nonnative/configuration_service_readiness.rb

Overview

Sinatra-based HTTP forward proxy server used as an in-process Nonnative server.

The proxy receives inbound HTTP requests and forwards them to an upstream host over HTTPS, returning the upstream response status and body.

This file defines two classes:

Notes:

See Also:

Defined Under Namespace

Modules: Cucumber Classes: CloseAllSocketPair, Configuration, ConfigurationFile, ConfigurationProcess, ConfigurationProxy, ConfigurationReadiness, ConfigurationRunner, ConfigurationServer, ConfigurationService, ConfigurationServiceReadiness, DelaySocketPair, Error, FaultInjectionProxy, GRPCHealth, GRPCProbe, GRPCServer, GoExecutable, HTTPClient, HTTPProbe, HTTPProxy, HTTPProxyServer, HTTPServer, Header, InvalidDataSocketPair, NoProxy, NotFoundError, Observability, Pool, Port, Ports, Process, Proxy, ProxyFactory, Runner, Server, Service, SocketPair, SocketPairFactory, StartError, StopError, TCPProbe, Timeout

Constant Summary collapse

VERSION =

The current gem version.

Returns:

  • (String)
'3.13.0'

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.pool ⇒ Nonnative::Pool?

Returns or overrides the current runner pool (created on start).

Returns:



126
127
128
# File 'lib/nonnative.rb', line 126

def pool
  @pool
end

Class Method Details

.clear ⇒ void

This method returns an undefined value.

Clears memoized configuration, logger, observability client, and pool.

Call this before reconfiguring Nonnative or starting a new lifecycle in the same Ruby process. start/stop are intended to manage one lifecycle for the current pool.



310
311
312
313
314
315
# File 'lib/nonnative.rb', line 310

def clear
  clear_logger
  clear_observability
  clear_configuration
  clear_pool
end

.clear_configuration ⇒ void

This method returns an undefined value.

Clears the memoized configuration instance.



277
278
279
# File 'lib/nonnative.rb', line 277

def clear_configuration
  @configuration = nil
end

.clear_logger ⇒ void

This method returns an undefined value.

Closes and clears the memoized logger instance.



284
285
286
287
288
# File 'lib/nonnative.rb', line 284

def clear_logger
  @logger&.close
ensure
  @logger = nil
end

.clear_observability ⇒ void

This method returns an undefined value.

Clears the memoized observability client.



293
294
295
# File 'lib/nonnative.rb', line 293

def clear_observability
  @observability = nil
end

.clear_pool ⇒ void

This method returns an undefined value.

Clears the memoized pool instance.



300
301
302
# File 'lib/nonnative.rb', line 300

def clear_pool
  @pool = nil
end

.configuration ⇒ Nonnative::Configuration

Returns the current configuration (memoized).



131
132
133
# File 'lib/nonnative.rb', line 131

def configuration
  @configuration ||= Nonnative::Configuration.new
end

.configure {|config| ... } ⇒ void

This method returns an undefined value.

Yields the configuration to a block for programmatic setup.

Examples:

Nonnative.configure do |config|
  config.name = 'my-service'
  # ...
end

Yield Parameters:



145
146
147
# File 'lib/nonnative.rb', line 145

def configure
  yield configuration
end

.go_argv(tools, output, exec, cmd, *params) ⇒ Array<String>

Builds a Go test executable argv array with optional profiling/trace/coverage flags.

Use this when passing argv entries directly to spawn.

Parameters:

  • tools (Array<String>) —

    enabled tool names (e.g. ["prof", "trace", "cover"])

  • output (String) —

    directory where outputs should be written

  • exec (String) —

    the test binary (or wrapper) to execute

  • cmd (String) —

    the command argument passed to the test binary

  • params (Array<String>) —

    extra parameter strings for the command

Returns:

  • (Array<String>) —

    executable argv entries



191
192
193
# File 'lib/nonnative.rb', line 191

def go_argv(tools, output, exec, cmd, *params)
  Nonnative::GoExecutable.new(tools, exec, output).argv(cmd, *params)
end

.go_command(tools, output, exec, cmd, *params) ⇒ String

Builds a Go test executable command string with optional profiling/trace/coverage flags.

Use this when passing a command string directly to spawn.

Parameters:

  • tools (Array<String>) —

    enabled tool names (e.g. ["prof", "trace", "cover"])

  • output (String) —

    directory where outputs should be written

  • exec (String) —

    the test binary (or wrapper) to execute

  • cmd (String) —

    the command argument passed to the test binary

  • params (Array<String>) —

    extra parameter strings for the command

Returns:

  • (String) —

    executable command string



177
178
179
# File 'lib/nonnative.rb', line 177

def go_command(tools, output, exec, cmd, *params)
  Nonnative::GoExecutable.new(tools, exec, output).command(cmd, *params)
end

.grpc_health(host:, port:, service:, timeout: 1) ⇒ Nonnative::GRPCHealth

Returns a client helper for the standard gRPC health checking protocol.

Parameters:

  • host (String) —

    gRPC server host

  • port (Integer) —

    gRPC server port

  • service (String) —

    gRPC health service name

  • timeout (Numeric) (defaults to: 1) —

    default call timeout in seconds

Returns:



207
# File 'lib/nonnative.rb', line 207

def grpc_health(host:, port:, service:, timeout: 1) = Nonnative::GRPCHealth.new(host: host, port: port, service: service, timeout: timeout)

.log_lines(path, predicate) ⇒ Array<String>

Reads a file and returns only lines matching the given predicate.

Parameters:

  • path (String) —

    file path to read

  • predicate (#call) —

    callable that receives a line and returns truthy/falsey

Returns:

  • (Array<String>) —

    matching lines



163
164
165
# File 'lib/nonnative.rb', line 163

def log_lines(path, predicate)
  File.readlines(path).select { |l| predicate.call(l) }
end

.logger ⇒ Logger

Returns the gem logger (memoized).

The logger writes to the path configured at Nonnative::Configuration#log.

Returns:

  • (Logger)


154
155
156
# File 'lib/nonnative.rb', line 154

def logger
  @logger ||= Logger.new(configuration.log)
end

.observability ⇒ Nonnative::Observability

Returns an HTTP client for common health/readiness endpoints.



198
# File 'lib/nonnative.rb', line 198

def observability = (@observability ||= Nonnative::Observability.new(configuration.url))

.proxies ⇒ Hash{String=>Class}

Returns the configured proxy kinds mapped to proxy classes.

Consumers can extend this map to add custom proxy implementations.

Returns:

  • (Hash{String=>Class})


214
215
216
# File 'lib/nonnative.rb', line 214

def proxies
  @proxies ||= { 'fault_injection' => Nonnative::FaultInjectionProxy }
end

.proxy(kind) ⇒ Class

Resolves a proxy implementation for a configured kind.

nil and "none" resolve to NoProxy; any other kind must be registered in proxies.

Parameters:

  • kind (String) —

    proxy kind name (for example "fault_injection")

Returns:

  • (Class) —

    a subclass of Proxy

Raises:

  • (ArgumentError) —

    if the kind is not "none" and has not been registered



226
227
228
# File 'lib/nonnative.rb', line 226

def proxy(kind)
  kind.nil? || kind == 'none' ? NoProxy : proxies.fetch(kind) { raise ArgumentError, "Unsupported proxy kind '#{kind}'" }
end

.reset ⇒ void

This method returns an undefined value.

Resets proxies for all currently started runners.

Raises:

  • (NoMethodError) —

    if called before start (because pool is nil)



321
322
323
# File 'lib/nonnative.rb', line 321

def reset
  Nonnative.pool.reset
end

.start ⇒ void

This method returns an undefined value.

Starts all configured services, servers, and processes, and waits for readiness.

Readiness is determined by attempting to connect to each runner's configured host/ports.

Raises:



236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/nonnative.rb', line 236

def start
  @pool ||= Nonnative::Pool.new(configuration)
  errors = []
  errors.concat(@pool.start do |name, values, result, ports|
    id, started = values
    errors << "Started #{name} with id #{id}, though did not respond in time for #{ports.description}" if !started || !result
  end)
  nil
rescue StandardError => e
  errors << unexpected_lifecycle_error(:start, e)
ensure
  if errors.any?
    errors.concat(rollback_start)

    raise Nonnative::StartError, errors.join("\n")
  end
end

.stop ⇒ void

This method returns an undefined value.

Stops all configured processes and servers, then services, and waits for shutdown.

Raises:



258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
# File 'lib/nonnative.rb', line 258

def stop
  errors = []
  return if @pool.nil?

  errors.concat(@pool.stop do |name, values, result, ports|
    id, stopped = Array(values).then { |v| [v.first, v.fetch(1, true)] }
    errors << "Stopped #{name} with id #{id}, though did not respond in time for #{ports.description}" unless result
    errors << "Stopped #{name} with id #{id}, though the process did not exit in time" unless stopped
  end)
  nil
rescue StandardError => e
  errors << unexpected_lifecycle_error(:stop, e)
ensure
  raise Nonnative::StopError, errors.join("\n") unless errors.empty?
end