|
| 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). |
0 commit comments