service

package
v0.0.0-...-e3a76c1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 17, 2026 License: MIT Imports: 33 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ContainerName

func ContainerName(instanceID, serviceName string) string

ContainerName returns the Docker container name for a service instance.

func ExecInContainer

func ExecInContainer(ctx context.Context, containerName string, cmd []string, stdout, stderr io.Writer) error

ExecInContainer runs a command inside a running container via docker exec. Output is written to stdout/stderr. Returns an error if the command exits with a non-zero status.

func PublishLocalEndpoints

func PublishLocalEndpoints(params PublishParams) (map[string]spec.Endpoint, error)

PublishLocalEndpoints is a shared implementation of Publish for service types that run locally. It maps each ingress to a 127.0.0.1 endpoint using the allocated port, preserving protocol and attributes.

Types

type ArtifactParams

type ArtifactParams struct {
	ServiceName string
	Spec        spec.Service
	Dir         string            // test process working directory (from SDK)
	HostEnv     map[string]string // host process env from SDK
}

ArtifactParams is passed to ArtifactProvider.Artifacts.

type ArtifactProvider

type ArtifactProvider interface {
	Artifacts(params ArtifactParams) ([]artifact.Artifact, error)
}

ArtifactProvider is implemented by service types that require artifacts (compiled binaries, pulled images, etc.) before starting. It is optional — service types that have no artifacts need not implement it.

type Backend

type Backend interface {
	// Start brings the backend up. Called once per key (e.g. per image).
	// Returns host, port for the running backend.
	Start(ctx context.Context) (host string, port int, err error)

	// Stop tears down the backend. Called when idle timer fires or on Close.
	Stop()

	// NewLease creates per-test isolation (e.g. CREATE DATABASE).
	// Returns a lease ID (e.g. "rig_3") and opaque data (e.g. container name).
	NewLease(ctx context.Context) (id string, data any, err error)

	// DropLease cleans up per-test isolation (e.g. DROP DATABASE).
	// Best-effort — called during Release, errors are not observed.
	DropLease(ctx context.Context, id string)
}

Backend defines the lifecycle operations for a pooled resource.

type Client

type Client struct{}

Client implements Type for the "client" service type. A client service delegates its start phase to a function in the client SDK via the callback protocol. The server allocates ports and health-checks normally; only the "start" step is handled client-side.

func (Client) Publish

func (Client) Publish(_ context.Context, params PublishParams) (map[string]spec.Endpoint, error)

Publish resolves ingress endpoints for a client service. Client services run locally, so they use the standard local publish.

func (Client) Runner

func (Client) Runner(params StartParams) run.Runner

Runner returns a runner that dispatches a start callback to the client, then idles until ctx is cancelled.

type ClientConfig

type ClientConfig struct {
	// StartHandler is the name of the client-side start callback.
	StartHandler string `json:"start_handler"`
}

ClientConfig is the type-specific config for "client" services.

type Container

type Container struct{}

Container implements Type for the "container" service type. It runs a Docker container with host-mapped ports.

func (Container) Artifacts

func (Container) Artifacts(params ArtifactParams) ([]artifact.Artifact, error)

Artifacts returns a DockerPull artifact for the configured image.

func (Container) Init

func (Container) Init(ctx context.Context, params InitParams) error

Init handles server-side init hooks for the container service type. Supports the "exec" hook type — runs a command inside the running container.

func (Container) Publish

func (Container) Publish(_ context.Context, params PublishParams) (map[string]spec.Endpoint, error)

Publish resolves ingress endpoints using host-allocated ports.

func (Container) Runner

func (Container) Runner(params StartParams) run.Runner

Runner returns a run.Runner that creates, starts, and manages a Docker container. The container is stopped and removed when ctx is cancelled.

type ContainerConfig

type ContainerConfig struct {
	// Image is the Docker image reference (e.g. "postgres:16").
	Image string `json:"image"`

	// Cmd overrides the container's default command.
	Cmd []string `json:"cmd,omitempty"`

	// Env sets additional environment variables on the container.
	// These are merged with the standard RIG_* wiring env vars.
	Env map[string]string `json:"env,omitempty"`
}

ContainerConfig is the type-specific config for "container" services.

type ExecHookConfig

type ExecHookConfig struct {
	Command []string `json:"command"`
}

ExecHookConfig is the Config payload for "exec" hooks.

type Go

type Go struct{}

Go implements Type for the "go" service type. It compiles a Go module during the artifact phase and runs the resulting binary during the service phase.

func (Go) Artifacts

func (Go) Artifacts(params ArtifactParams) ([]artifact.Artifact, error)

Artifacts returns the GoBuild artifact for this service. Implements ArtifactProvider.

func (Go) Publish

func (Go) Publish(_ context.Context, params PublishParams) (map[string]spec.Endpoint, error)

Publish resolves ingress endpoints for a go service.

func (Go) Runner

func (Go) Runner(params StartParams) run.Runner

Runner looks up the compiled binary from the artifact results and returns a run.Process that executes it with the resolved wiring.

type GoServiceConfig

type GoServiceConfig struct {
	// Module is an absolute local path ("/abs/path/cmd/server"), a relative
	// path ("./cmd/server") resolved against the environment's Dir, or a
	// remote module reference ("github.com/myorg/tool@v1.2.3").
	Module string `json:"module"`
}

GoServiceConfig is the type-specific config for "go" services.

type InitParams

type InitParams struct {
	ServiceName string
	InstanceID  string
	Spec        spec.Service
	Ingresses   map[string]spec.Endpoint
	Egresses    map[string]spec.Endpoint
	Hook        *spec.HookSpec
	Stdout      io.Writer
	Stderr      io.Writer
}

InitParams provides the context needed for server-side init hook execution.

type Initializer

type Initializer interface {
	Init(ctx context.Context, params InitParams) error
}

Initializer is implemented by service types that handle server-side init hooks (e.g. Postgres running SQL via docker exec). It is optional — service types that only use client_func hooks need not implement it.

Initializer hooks run during the init phase only (after the service is healthy). Prestart hooks must be client_func — the service isn't running yet so there's nothing to exec into.

type Kafka

type Kafka struct{}

Kafka implements Type, ArtifactProvider, and Initializer for the "kafka" builtin service type. Each test gets a fresh Redpanda container (no pool).

func (Kafka) Artifacts

func (Kafka) Artifacts(params ArtifactParams) ([]artifact.Artifact, error)

Artifacts returns a DockerPull artifact for the Redpanda image.

func (Kafka) Init

func (Kafka) Init(ctx context.Context, params InitParams) error

Init handles server-side init hooks for the Kafka service type. Supports the "schema" hook type — registers a schema with the schema registry.

func (Kafka) Publish

func (Kafka) Publish(ctx context.Context, params PublishParams) (map[string]spec.Endpoint, error)

Publish resolves ingress endpoints using host-allocated ports.

func (Kafka) Runner

func (Kafka) Runner(params StartParams) run.Runner

Runner builds a ContainerConfig and delegates to Container{}.Runner.

type KafkaConfig

type KafkaConfig struct {
	Image string `json:"image,omitempty"`
}

KafkaConfig is the type-specific config for "kafka" services.

type Lease

type Lease struct {
	ID   string // e.g. "rig_3"
	Host string // e.g. "127.0.0.1"
	Port int    // e.g. 54321
	Data any    // backend-specific (e.g. container name for Postgres)
	// contains filtered or unexported fields
}

Lease represents a single test environment's claim on a shared instance.

type Pool

type Pool struct {
	// contains filtered or unexported fields
}

Pool manages shared backend instances. Each unique key gets one instance; individual test environments get isolated leases within it.

func NewPool

func NewPool(factory func(key string) Backend, idleTime time.Duration) *Pool

NewPool creates a new pool. The factory function creates a Backend for each unique key. idleTime controls how long an instance lingers after its last lease is released before being stopped.

func NewPostgresPool

func NewPostgresPool(pid int) *Pool

NewPostgresPool creates a Pool backed by Postgres containers. Each unique image key gets one shared container; individual test environments get isolated databases within it. The pid is embedded in container names so multiple rigd processes never collide.

func NewRedisPool

func NewRedisPool(pid int) *Pool

NewRedisPool creates a Pool backed by Redis containers. Each unique image key gets one shared container; individual test environments get isolated databases within it. The pid is embedded in container names so multiple rigd processes never collide.

func NewS3Pool

func NewS3Pool(pid int) *Pool

NewS3Pool creates a Pool backed by MinIO containers. A single shared container per rigd process provides S3-compatible object storage; individual test environments get isolated buckets within it.

The idle timeout is set longer than rigd's own 5-minute idle shutdown, so in practice the container lives for the lifetime of the rigd process. If rigd ever runs indefinitely, this timeout provides a safety net.

func NewSQSPool

func NewSQSPool(pid int) *Pool

NewSQSPool creates a Pool backed by ElasticMQ containers. A single shared container per rigd process provides SQS-compatible messaging; individual test environments get isolated queues within it.

func NewTemporalPool

func NewTemporalPool(cacheDir string) *Pool

NewTemporalPool creates a Pool backed by Temporal dev server processes. Each unique version key gets one shared process; individual test environments get isolated namespaces within it. cacheDir is the artifact cache root (e.g. {rigDir}/cache) used to resolve/locate the Temporal CLI binary.

func (*Pool) Acquire

func (p *Pool) Acquire(ctx context.Context, key string) (*Lease, error)

Acquire returns a lease for the backend identified by key. The first call for a key starts the backend; subsequent calls reuse it. If the backend start fails, the instance resets to allow retry by the next caller — a transient failure or cancelled context doesn't poison the pool.

func (*Pool) Close

func (p *Pool) Close()

Close stops all backend instances. Called on server shutdown.

func (*Pool) Release

func (p *Pool) Release(lease *Lease)

Release drops a lease, cleaning up per-test isolation and decrementing the refcount. When refcount hits zero, an idle timer starts; if no new Acquire happens before it fires, the backend is stopped.

type Postgres

type Postgres struct {
	// contains filtered or unexported fields
}

Postgres implements Type and ArtifactProvider for the "postgres" builtin service type. It uses a Pool to share containers across environments, providing per-test database isolation.

func NewPostgres

func NewPostgres(pool *Pool) *Postgres

NewPostgres creates a Postgres service type backed by the given pool.

func (*Postgres) Artifacts

func (p *Postgres) Artifacts(params ArtifactParams) ([]artifact.Artifact, error)

Artifacts returns a DockerPull artifact for the Postgres image. The pool manages containers, but the artifact phase still ensures the image is pulled before any Acquire call.

func (*Postgres) Init

func (p *Postgres) Init(ctx context.Context, params InitParams) error

Init handles server-side hooks for the Postgres service type. Supports "sql" (runs each statement via psql against the per-test DB) and "exec" (runs an arbitrary command inside the shared container).

func (*Postgres) Publish

func (p *Postgres) Publish(ctx context.Context, params PublishParams) (map[string]spec.Endpoint, error)

Publish acquires a lease from the pool (which creates the per-test database) and returns an endpoint using the shared container's port and unique DB name.

func (*Postgres) ReadyCheck

func (p *Postgres) ReadyCheck(params ReadyCheckParams) ready.Checker

ReadyCheck returns a checker that runs pg_isready against the shared container. Since the container is already healthy from the pool, this should pass quickly.

func (*Postgres) Runner

func (p *Postgres) Runner(params StartParams) run.Runner

Runner returns a runner that blocks on ctx and releases the lease on exit. The shared container is managed by the pool — no per-test container start.

type PostgresConfig

type PostgresConfig struct {
	// Image overrides the default Postgres Docker image.
	Image string `json:"image,omitempty"`
}

PostgresConfig is the type-specific config for "postgres" services.

type Process

type Process struct{}

Process implements Type for the "process" service type. It runs an external binary with arguments and environment variables.

func (Process) Publish

func (Process) Publish(_ context.Context, params PublishParams) (map[string]spec.Endpoint, error)

Publish resolves ingress endpoints for a process service.

func (Process) Runner

func (Process) Runner(params StartParams) run.Runner

Runner returns a run.Process that executes the configured binary.

type ProcessConfig

type ProcessConfig struct {
	// Command is the path to the executable.
	Command string `json:"command"`

	// Dir is the working directory. Optional.
	Dir string `json:"dir,omitempty"`
}

ProcessConfig is the type-specific config for "process" services.

type Proxy

type Proxy struct {
	// contains filtered or unexported fields
}

Proxy implements service.Type for transparent traffic proxy nodes. These are injected by the spec transformation and are not user-facing. Holds an in-memory reflection cache shared across all proxy instances within a single rigd process, avoiding redundant reflection probes for the same gRPC service across test runs.

func NewProxy

func NewProxy() *Proxy

NewProxy creates a Proxy with an initialized reflection cache.

func (*Proxy) Publish

func (p *Proxy) Publish(_ context.Context, params PublishParams) (map[string]spec.Endpoint, error)

Publish resolves the proxy's ingress endpoint by copying the target's protocol and attributes from the resolved "target" egress, then binding to the allocated port.

func (*Proxy) Runner

func (p *Proxy) Runner(params StartParams) run.Runner

Runner starts the proxy forwarder, relaying traffic from the allocated listen port to the real target endpoint.

type ProxyConfig

type ProxyConfig struct {
	Source        string `json:"source"`                   // consuming service name or "~test"
	TargetSvc     string `json:"target_svc"`               // real target service name
	Ingress       string `json:"ingress"`                  // real target ingress name
	ReflectionKey string `json:"reflection_key,omitempty"` // cache key for gRPC reflection descriptors
}

ProxyConfig is the type-specific config for a proxy service node. Stored in spec.Service.Config as JSON.

type PublishParams

type PublishParams struct {
	ServiceName string
	InstanceID  string // environment instance ID
	Spec        spec.Service
	Ingresses   map[string]spec.IngressSpec
	Ports       map[string]int           // ingress name → allocated port
	Egresses    map[string]spec.Endpoint // resolved egresses (from wiring, may be nil for leaf services)
}

PublishParams provides the context needed for the publish phase.

type ReadyCheckParams

type ReadyCheckParams struct {
	ServiceName string
	InstanceID  string
	IngressName string
	Endpoint    spec.Endpoint
	Spec        spec.Service
}

ReadyCheckParams provides context for building a custom ready checker.

type ReadyChecker

type ReadyChecker interface {
	ReadyCheck(params ReadyCheckParams) ready.Checker
}

ReadyChecker is implemented by service types that provide a custom health check (e.g. Postgres using pg_isready instead of TCP dial). Optional — service types without this use the default protocol-based check.

When implemented, the custom checker replaces the default checker entirely — including any ReadySpec.Type on the ingress. Timeout and interval from the ReadySpec are still honored by the polling loop.

type Redis

type Redis struct {
	// contains filtered or unexported fields
}

Redis implements Type and ArtifactProvider for the "redis" builtin service type. It uses a Pool to share containers across environments, providing per-test database isolation.

func NewRedis

func NewRedis(pool *Pool) *Redis

NewRedis creates a Redis service type backed by the given pool.

func (*Redis) Artifacts

func (r *Redis) Artifacts(params ArtifactParams) ([]artifact.Artifact, error)

Artifacts returns a DockerPull artifact for the Redis image. The pool manages containers, but the artifact phase still ensures the image is pulled before any Acquire call.

func (*Redis) Publish

func (r *Redis) Publish(ctx context.Context, params PublishParams) (map[string]spec.Endpoint, error)

Publish acquires a lease from the pool (which allocates a per-test database) and returns an endpoint using the shared container's port and unique db number.

func (*Redis) Runner

func (r *Redis) Runner(params StartParams) run.Runner

Runner returns a runner that blocks on ctx and releases the lease on exit. The shared container is managed by the pool — no per-test container start.

type RedisConfig

type RedisConfig struct {
	Image string `json:"image,omitempty"`
}

RedisConfig is the type-specific config for "redis" services.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry maps service type names to their implementations.

func NewRegistry

func NewRegistry() *Registry

NewRegistry creates a registry with no types registered.

func (*Registry) Get

func (r *Registry) Get(name string) (Type, error)

Get returns the service type for the given name, or an error if not found.

func (*Registry) Register

func (r *Registry) Register(name string, t Type)

Register adds a service type to the registry.

type S3

type S3 struct {
	// contains filtered or unexported fields
}

S3 implements Type and ArtifactProvider for the "s3" builtin service type. It uses a Pool to share a single MinIO container across environments, providing per-test bucket isolation.

func NewS3

func NewS3(pool *Pool) *S3

NewS3 creates an S3 service type backed by the given pool.

func (*S3) Artifacts

func (s *S3) Artifacts(params ArtifactParams) ([]artifact.Artifact, error)

Artifacts returns a DockerPull artifact for the MinIO image.

func (*S3) Publish

func (s *S3) Publish(ctx context.Context, params PublishParams) (map[string]spec.Endpoint, error)

Publish acquires a lease from the pool (which creates a per-test bucket) and returns an endpoint with S3 connection attributes.

func (*S3) Runner

func (s *S3) Runner(params StartParams) run.Runner

Runner returns a runner that blocks on ctx and releases the lease on exit.

type SQS

type SQS struct {
	// contains filtered or unexported fields
}

SQS implements Type and ArtifactProvider for the "sqs" builtin service type. It uses a Pool to share a single ElasticMQ container across environments, providing per-test queue isolation.

func NewSQS

func NewSQS(pool *Pool) *SQS

NewSQS creates an SQS service type backed by the given pool.

func (*SQS) Artifacts

func (s *SQS) Artifacts(params ArtifactParams) ([]artifact.Artifact, error)

Artifacts returns a DockerPull artifact for the ElasticMQ image.

func (*SQS) Publish

func (s *SQS) Publish(ctx context.Context, params PublishParams) (map[string]spec.Endpoint, error)

Publish acquires a lease from the pool (which creates a per-test queue) and returns an endpoint with SQS connection attributes.

func (*SQS) Runner

func (s *SQS) Runner(params StartParams) run.Runner

Runner returns a runner that blocks on ctx and releases the lease on exit.

type StartParams

type StartParams struct {
	ServiceName string
	Spec        spec.Service
	Ingresses   map[string]spec.Endpoint   // resolved ingresses (from publish)
	Egresses    map[string]spec.Endpoint   // resolved egresses (from wiring)
	Artifacts   map[string]artifact.Output // keyed by Artifact.Key (from artifact phase)
	Env         map[string]string          // pre-built environment variables
	Args        []string                   // raw command arg templates (expand against Env or adjusted env)
	TempDir     string
	EnvDir      string
	Dir         string // default working directory for child processes (from SDK)
	InstanceID  string // environment instance ID (used for container naming)
	Stdout      io.Writer
	Stderr      io.Writer

	// BuildEnv produces a complete env var map from the given endpoints.
	// Service types that need to adjust endpoints for a different network
	// namespace (e.g. containers) call this with modified endpoints instead
	// of patching the flat Env map directly.
	BuildEnv func(ingresses, egresses map[string]spec.Endpoint) (map[string]string, error)

	// Callback dispatches a callback request to the client SDK and blocks
	// until the response arrives. Nil for types that don't use callbacks.
	Callback func(ctx context.Context, name, callbackType string) error

	// ProxyEmit publishes a proxy event to the event log. Set for proxy
	// service types; nil for all others.
	ProxyEmit func(proxy.Event)
}

StartParams provides the context needed for the start phase.

type Temporal

type Temporal struct {
	// contains filtered or unexported fields
}

Temporal implements Type and ArtifactProvider for the "temporal" builtin service type. It uses a Pool to share dev server processes across environments, providing per-test namespace isolation.

func NewTemporal

func NewTemporal(pool *Pool) *Temporal

NewTemporal creates a Temporal service type backed by the given pool.

func (*Temporal) Artifacts

func (t *Temporal) Artifacts(params ArtifactParams) ([]artifact.Artifact, error)

Artifacts returns a Download artifact for the Temporal CLI binary. The pool manages processes, but the artifact phase still ensures the binary is downloaded before any Acquire call.

func (*Temporal) Publish

func (t *Temporal) Publish(ctx context.Context, params PublishParams) (map[string]spec.Endpoint, error)

Publish acquires a lease from the pool (which creates a per-test namespace) and returns endpoints using the shared process's ports.

func (*Temporal) Runner

func (t *Temporal) Runner(params StartParams) run.Runner

Runner returns a runner that blocks on ctx and releases the lease on exit. The shared process is managed by the pool — no per-test subprocess.

type TemporalConfig

type TemporalConfig struct {
	Version string `json:"version,omitempty"`
}

TemporalConfig is the type-specific config for "temporal" services.

type Test

type Test struct{}

Test implements service.Type for the virtual ~test node. It has no ingresses and blocks until context cancellation. Its only purpose is to participate in the service lifecycle so that waitForEgressesStep gates on all real services being READY, and emitEnvironmentUp fires from its lifecycle.

func (Test) Publish

func (Test) Publish(_ context.Context, _ PublishParams) (map[string]spec.Endpoint, error)

Publish returns nil — the ~test node has no ingresses.

func (Test) Runner

func (Test) Runner(_ StartParams) run.Runner

Runner returns run.Idle — blocks until context is cancelled.

type Type

type Type interface {
	// Publish resolves ingress endpoints for this service. Called after ports
	// are allocated. Returns the fully resolved ingress endpoints.
	Publish(ctx context.Context, params PublishParams) (map[string]spec.Endpoint, error)

	// Runner returns a run.Runner that starts and runs the service.
	// The runner should block until the service exits or ctx is cancelled.
	Runner(params StartParams) run.Runner
}

Type defines how a service type publishes endpoints and starts.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL