Documentation
¶
Overview ¶
Package agent is stampede agent: a helper that runs inside the user's environment and injects faults into dependencies during a load test.
It places TCP proxies in front of dependencies (a database, a cache, a downstream API) and, on request, adds latency and jitter, limits bandwidth, resets connections, refuses new ones or stops forwarding. With explicit flags it can also pause, stop or restart Docker containers and scale Kubernetes deployments. Every fault has a duration and is reverted when it ends, when it is cleared (the kill switch), or when the agent stops. Every action is written to an audit log.
Index ¶
- Variables
- type Active
- type Agent
- func (a *Agent) Active() []Active
- func (a *Agent) Apply(ctx context.Context, req Request) (*Active, error)
- func (a *Agent) Handler(token string) http.Handler
- func (a *Agent) Proxies() []ProxyInfo
- func (a *Agent) Revert(ctx context.Context, id, why string) error
- func (a *Agent) RevertAll(ctx context.Context, run, why string) error
- type Client
- type Config
- type Docker
- type Fault
- type Kind
- type Kubernetes
- type Proxy
- type ProxyInfo
- type Request
- type Status
Constants ¶
This section is empty.
Variables ¶
var ErrNotAllowed = errors.New("not allowed")
ErrNotAllowed means the agent was not started with permission for the action.
Functions ¶
This section is empty.
Types ¶
type Active ¶
type Active struct {
ID string `json:"id"`
Request Request `json:"request"`
Started time.Time `json:"started"`
Ends time.Time `json:"ends"`
// contains filtered or unexported fields
}
Active is a fault in force.
type Agent ¶
type Agent struct {
// contains filtered or unexported fields
}
Agent applies and reverts faults.
func (*Agent) Apply ¶
Apply starts a fault. It replaces any fault already active on the same target, and reverts by itself after the duration.
func (*Agent) Handler ¶
Handler serves the control API. Every request needs "Authorization: Bearer <token>".
GET /v1/status
POST /v1/faults a Request; answers the Active fault
DELETE /v1/faults/{id} revert one fault
DELETE /v1/faults?run=ID revert every fault (of one run): the kill switch
type Client ¶
Client talks to an agent's control API.
type Config ¶
type Config struct {
Proxies []*Proxy
// Docker, when set, allows container actions.
Docker *Docker
// Kubernetes, when set, allows deployment scaling.
Kubernetes *Kubernetes
// MaxDuration caps every fault (default 30 minutes), so a forgotten
// fault always ends.
MaxDuration time.Duration
// Audit receives one record per action and revert.
Audit *slog.Logger
Logger *slog.Logger
}
Config configures an Agent.
type Docker ¶
type Docker struct {
// Allowed lists container names (globs) the agent may act on.
Allowed []string
// contains filtered or unexported fields
}
Docker acts on containers through the Docker Engine API.
type Fault ¶
type Fault struct {
// Latency is added to each direction of every connection, so a
// request and its response together take twice Latency longer.
Latency time.Duration `json:"latency,omitempty"`
// Jitter adds a random delay in [0, Jitter) on top of Latency.
Jitter time.Duration `json:"jitter,omitempty"`
// Bandwidth caps each direction of each connection, in bytes per
// second (0 = unlimited).
Bandwidth int64 `json:"bandwidth,omitempty"`
// Reset resets every open connection when the fault starts, and every
// new connection while it lasts.
Reset bool `json:"reset,omitempty"`
// Refuse resets new connections as soon as they arrive; open ones are
// left alone.
Refuse bool `json:"refuse,omitempty"`
// Blackhole stops forwarding in both directions: connections stay
// open and requests time out.
Blackhole bool `json:"blackhole,omitempty"`
}
Fault is what a proxy does to traffic while the fault is active. The zero Fault forwards traffic untouched.
func (Fault) MarshalJSON ¶
MarshalJSON writes durations as strings.
func (*Fault) UnmarshalJSON ¶
UnmarshalJSON reads durations as strings.
type Kubernetes ¶
type Kubernetes struct {
// Allowed lists deployments (namespace/name globs) the agent may scale.
Allowed []string
// contains filtered or unexported fields
}
Kubernetes scales deployments through the API server, with the pod's service account when running in a cluster.
func NewKubernetes ¶
func NewKubernetes(base, token string, allowedDeployments []string) (*Kubernetes, error)
NewKubernetes uses the in-cluster service account, or base and token when given (tests, or a kubectl proxy at http://127.0.0.1:8001).
type Proxy ¶
type Proxy struct {
Name string
Listen string
Upstream string
// contains filtered or unexported fields
}
Proxy forwards TCP connections from Listen to Upstream, applying the current fault.
type ProxyInfo ¶
type ProxyInfo struct {
Name string `json:"name"`
Listen string `json:"listen"`
Upstream string `json:"upstream"`
Conns int `json:"conns"`
Fault Fault `json:"fault"`
}
ProxyInfo describes a proxy.
type Request ¶
type Request struct {
Kind Kind `json:"kind"`
// Target is a proxy name, a container name or id, or a deployment as
// namespace/name.
Target string `json:"target"`
// Fault applies to proxies.
Fault Fault `json:"fault,omitempty"`
// Action applies to containers: pause, stop or restart.
Action string `json:"action,omitempty"`
// Replicas applies to deployments.
Replicas *int `json:"replicas,omitempty"`
// Duration is how long the fault lasts; required, at most MaxDuration.
Duration time.Duration `json:"duration"`
// Run and Label say who asked, for the audit log.
Run string `json:"run,omitempty"`
Label string `json:"label,omitempty"`
}
Request asks for one fault for a while.
func (Request) MarshalJSON ¶
MarshalJSON writes the duration as a string.
func (*Request) UnmarshalJSON ¶
UnmarshalJSON reads the duration as a string.