Skip to content

Commit 51be24f

Browse files
Toxiproxy
1 parent 081d9c8 commit 51be24f

File tree

2 files changed

+21
-55
lines changed

2 files changed

+21
-55
lines changed

docs/modules/toxiproxy.md

Lines changed: 15 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,35 @@
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.
1+
# Toxiproxy
132

143
## Install
4+
155
```bash
166
npm install @testcontainers/toxiproxy --save-dev
177
```
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.
238

24-
Next, it is necessary to instruct Toxiproxy to start proxying connections.
25-
Each `ToxiProxyContainer` can proxy to many target containers if necessary.
9+
## Examples
2610

27-
A proxy is created by calling `createProxy` on the `ToxiProxyContainer` instance.
11+
These examples use the following libraries:
2812

29-
The client connecting to the proxied endpoint then needs to use the exposed port from the returned proxy.
13+
- [toxiproxy-node-client](https://www.npmjs.com/package/toxiproxy-node-client)
3014

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-->
15+
npm install toxiproxy-node-client
3516

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.
17+
Choose an image from the [container registry](https://github.com/Shopify/toxiproxy/pkgs/container/toxiproxy) and substitute `IMAGE`.
3818

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:
19+
### Create a proxy
5520

5621
<!--codeinclude-->
57-
[Adding latency to a connection](../../packages/modules/toxiproxy/src/toxiproxy-container.test.ts) inside_block:adding_toxic
22+
[](../../packages/modules/toxiproxy/src/toxiproxy-container.test.ts) inside_block:create_proxy
5823
<!--/codeinclude-->
5924

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.
25+
### Add a toxic
6126

6227
<!--codeinclude-->
63-
[Enable and disable the proxy:](../../packages/modules/toxiproxy/src/toxiproxy-container.test.ts) inside_block:enabled_disabled
28+
[](../../packages/modules/toxiproxy/src/toxiproxy-container.test.ts) inside_block:adding_toxic
6429
<!--/codeinclude-->
6530

66-
## Acknowledgements
31+
### Enable/disable the proxy
6732

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).
33+
<!--codeinclude-->
34+
[](../../packages/modules/toxiproxy/src/toxiproxy-container.test.ts) inside_block:enabled_disabled
35+
<!--/codeinclude-->

packages/modules/toxiproxy/src/toxiproxy-container.test.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import { ToxiProxyContainer, TPClient } from "./toxiproxy-container";
55
const IMAGE = getImage(__dirname);
66

77
describe("ToxiProxyContainer", { timeout: 240_000 }, () => {
8-
// create_proxy {
98
it("should create a proxy to an endpoint", async () => {
9+
// create_proxy {
1010
await using network = await new Network().start();
1111
await using _ = await new GenericContainer("cristianrgreco/testcontainer:1.1.14")
1212
.withExposedPorts(8080)
@@ -23,11 +23,11 @@ describe("ToxiProxyContainer", { timeout: 240_000 }, () => {
2323

2424
const response = await fetch(`http://${appProxy.host}:${appProxy.port}/hello-world`);
2525
expect(response.status).toBe(200);
26+
// }
2627
});
27-
// }
2828

29-
// enabled_disabled {
3029
it("should enable and disable a proxy", async () => {
30+
// enabled_disabled {
3131
await using network = await new Network().start();
3232
await using _ = await new GenericContainer("cristianrgreco/testcontainer:1.1.14")
3333
.withExposedPorts(8080)
@@ -48,11 +48,11 @@ describe("ToxiProxyContainer", { timeout: 240_000 }, () => {
4848
await appProxy.setEnabled(true);
4949
const response = await fetch(`http://${appProxy.host}:${appProxy.port}/hello-world`);
5050
expect(response.status).toBe(200);
51+
// }
5152
});
52-
// }
5353

54-
// adding_toxic {
5554
it("should add a toxic to a proxy and then remove", async () => {
55+
// adding_toxic {
5656
await using network = await new Network().start();
5757
await using _ = await new GenericContainer("cristianrgreco/testcontainer:1.1.14")
5858
.withExposedPorts(8080)
@@ -67,7 +67,6 @@ describe("ToxiProxyContainer", { timeout: 240_000 }, () => {
6767
upstream: "app:8080",
6868
});
6969

70-
// See https://github.com/ihsw/toxiproxy-node-client for details on the instance interface
7170
const toxic = await appProxy.instance.addToxic<TPClient.Latency>({
7271
attributes: {
7372
jitter: 50,
@@ -85,8 +84,8 @@ describe("ToxiProxyContainer", { timeout: 240_000 }, () => {
8584
expect(after - before).toBeGreaterThan(1000);
8685

8786
await toxic.remove();
87+
// }
8888
});
89-
// }
9089

9190
it("should create multiple proxies", async () => {
9291
await using network = await new Network().start();

0 commit comments

Comments
 (0)