Skip to content

Commit 6bee7da

Browse files
committed
feat: Add toxiproxy module
1 parent ba73759 commit 6bee7da

File tree

10 files changed

+484
-30
lines changed

10 files changed

+484
-30
lines changed

docs/modules/toxiproxy.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Toxiproxy Module
2+
3+
Testcontainers module for Shopify's [Toxiproxy](https://github.com/Shopify/toxiproxy).
4+
This TCP proxy can be used to simulate network failure conditions.
5+
6+
You can simulate network failures:
7+
8+
* between NodeJS code and containers, ideal for testing resilience features of client code
9+
* between containers, for testing resilience and emergent behaviour of multi-container systems
10+
* if desired, between NodeJS code/containers and external resources (non-Dockerized!), for scenarios where not all dependencies can be/have been dockerized
11+
12+
Testcontainers Toxiproxy support allows resilience features to be easily verified as part of isolated dev/CI testing. This allows earlier testing of resilience features, and broader sets of failure conditions to be covered.
13+
14+
## Install
15+
```bash
16+
npm install @testcontainers/toxiproxy --save-dev
17+
```
18+
19+
## Usage example
20+
21+
A Toxiproxy container can be placed in between test code and a container, or in between containers.
22+
In either scenario, it is necessary to create a `ToxiProxyContainer` instance on the same Docker network.
23+
24+
Next, it is necessary to instruct Toxiproxy to start proxying connections.
25+
Each `ToxiProxyContainer` can proxy to many target containers if necessary.
26+
27+
A proxy is created by calling `createProxy` on the `ToxiProxyContainer` instance.
28+
29+
The client connecting to the proxied endpoint then needs to use the exposed port from the returned proxy.
30+
31+
All of this is done as follows:
32+
<!--codeinclude-->
33+
[Creating, starting and using the container:](../../packages/modules/toxiproxy/src/toxiproxy-container.test.ts) inside_block:create_proxy
34+
<!--/codeinclude-->
35+
36+
!!! note
37+
Currently, `ToxiProxyContainer` will reserve 31 ports, starting at 8666. After this, trying to create a new proxy instance will throw an error.
38+
39+
40+
Having done all of this, it is possible to trigger failure conditions ('Toxics') through the `proxy.instance.addToxic<TPClient.TOXIC_TYPE>()` object:
41+
42+
`TPClient` is the internal `toxiproxy-node-client` re-exported in this package.
43+
44+
* `bandwidth` - Limit a connection to a maximum number of kilobytes per second.
45+
* `latency` - Add a delay to all data going through the proxy. The delay is equal to `latency +/- jitter`.
46+
* `slicer` - Slices TCP data up into small bits, optionally adding a delay between each sliced "packet".
47+
* `slow_close` - Delay the TCP socket from closing until `delay` milliseconds has elapsed.
48+
* `timeout` - Stops all data from getting through, and closes the connection after `timeout`. If `timeout` is `0`, the connection won't close, and data will be delayed until the toxic is removed.
49+
* `limit_data` - Closes connection when transmitted data exceeded limit.
50+
* `reset_peer` - Simulate TCP RESET (Connection reset by peer) on the connections
51+
52+
Please see the [Toxiproxy documentation](https://github.com/Shopify/toxiproxy#toxics) and the [toxiproxy-node-client](https://github.com/ihsw/toxiproxy-node-client) for full details on the available Toxics.
53+
54+
As one example, we can introduce latency and random jitter to proxied connections as follows:
55+
56+
<!--codeinclude-->
57+
[Adding latency to a connection](../../packages/modules/toxiproxy/src/toxiproxy-container.test.ts) inside_block:adding_toxic
58+
<!--/codeinclude-->
59+
60+
There is also a helper method to enable / disable specific proxy instances (for more fine-grained control instead of using the `reset_peer` toxic). This can also be done by calling the `proxy.instance.update` method, however it is more complicated as you'll need to supply the upstream again and the internal listening port.
61+
62+
<!--codeinclude-->
63+
[Enable and disable the proxy:](../../packages/modules/toxiproxy/src/toxiproxy-container.test.ts) inside_block:enabled_disabled
64+
<!--/codeinclude-->
65+
66+
## Acknowledgements
67+
68+
This module was inspired by the Java implementation, and under the hood uses the [toxiproxy-node-client](https://github.com/ihsw/toxiproxy-node-client).

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,5 +67,6 @@ nav:
6767
- Redpanda: modules/redpanda.md
6868
- ScyllaDB: modules/scylladb.md
6969
- Selenium: modules/selenium.md
70+
- ToxiProxy: modules/toxiproxy.md
7071
- Weaviate: modules/weaviate.md
7172
- Configuration: configuration.md

package-lock.json

Lines changed: 55 additions & 30 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import type { Config } from "jest";
2+
import * as path from "path";
3+
4+
const config: Config = {
5+
preset: "ts-jest",
6+
moduleNameMapper: {
7+
"^testcontainers$": path.resolve(__dirname, "../../testcontainers/src"),
8+
},
9+
};
10+
11+
export default config;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"name": "@testcontainers/toxiproxy",
3+
"version": "10.16.0",
4+
"license": "MIT",
5+
"keywords": [
6+
"toxiproxy",
7+
"testing",
8+
"docker",
9+
"testcontainers"
10+
],
11+
"description": "Toxiproxy module for Testcontainers",
12+
"homepage": "https://github.com/testcontainers/testcontainers-node#readme",
13+
"repository": {
14+
"type": "git",
15+
"url": "https://github.com/testcontainers/testcontainers-node"
16+
},
17+
"bugs": {
18+
"url": "https://github.com/testcontainers/testcontainers-node/issues"
19+
},
20+
"main": "build/index.js",
21+
"files": [
22+
"build"
23+
],
24+
"publishConfig": {
25+
"access": "public"
26+
},
27+
"scripts": {
28+
"prepack": "shx cp ../../../README.md . && shx cp ../../../LICENSE .",
29+
"build": "tsc --project tsconfig.build.json"
30+
},
31+
"dependencies": {
32+
"testcontainers": "^10.16.0",
33+
"toxiproxy-node-client": "^4.0.0"
34+
},
35+
"devDependencies": {
36+
"@testcontainers/redis": "^10.16.0",
37+
"redis": "^4.7.0"
38+
}
39+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { ToxiProxyContainer, StartedToxiProxyContainer, CreatedProxy } from "./toxiproxy-container";

0 commit comments

Comments
 (0)