1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
# toxiproxy-go
This is the Go client library for the
[Toxiproxy](https://github.com/shopify/toxiproxy) API. Please read the [usage
section in the Toxiproxy README](https://github.com/shopify/toxiproxy#usage)
before attempting to use the client.
This client is compatible with Toxiproxy 2.x, for the latest 1.x client see
[v1.2.1](https://github.com/Shopify/toxiproxy/tree/v1.2.1/client).
## Changes in Toxiproxy-go Client 2.x
In order to make use of the 2.0 api, and to make usage a little easier, the
client api has changed:
- `client.NewProxy()` no longer accepts a proxy as an argument.
- `proxy.Create()` is removed in favour of using `proxy.Save()`.
- Proxies can be created in a single call using `client.CreateProxy()`.
- `proxy.Disable()` and `proxy.Enable()` have been added to simplify taking
down a proxy.
- `proxy.ToxicsUpstream` and `proxy.ToxicsDownstream` have been merged into a
single `ActiveToxics` list.
- `proxy.Toxics()`` no longer requires a direction to be specified, and will
return toxics for both directions.
- `proxy.SetToxic()` has been replaced by `proxy.AddToxic()`,
`proxy.UpdateToxic()`, and `proxy.RemoveToxic()`.
## Usage
For detailed API docs please [see the Godoc
documentation](http://godoc.org/github.com/Shopify/toxiproxy/client).
First import toxiproxy and create a new client:
```go
import "github.com/Shopify/toxiproxy/client"
client := toxiproxy.NewClient("localhost:8474")
```
You can then create a new proxy using the client:
```go
proxy := client.CreateProxy("redis", "localhost:26379", "localhost:6379")
```
For large amounts of proxies, they can also be created using a configuration file:
```go
var config []toxiproxy.Proxy
data, _ := ioutil.ReadFile("config.json")
json.Unmarshal(data, &config)
proxies, err = client.Populate(config)
```
```json
[{
"name": "redis",
"listen": "localhost:26379",
"upstream": "localhost:6379"
}]
```
Toxics can be added as follows:
```go
// Add 1s latency to 100% of downstream connections
proxy.AddToxic("latency_down", "latency", "downstream", 1.0, toxiproxy.Attributes{
"latency": 1000,
})
// Change downstream latency to add 100ms of jitter
proxy.UpdateToxic("latency_down", 1.0, toxiproxy.Attributes{
"jitter": 100,
})
// Remove the latency toxic
proxy.RemoveToxic("latency_down")
```
The proxy can be taken down using `Disable()`:
```go
proxy.Disable()
```
When a proxy is no longer needed, it can be cleaned up with `Delete()`:
```go
proxy.Delete()
```
## Full Example
```go
import (
"net/http"
"testing"
"time"
"github.com/Shopify/toxiproxy/client"
"github.com/garyburd/redigo/redis"
)
var toxiClient *toxiproxy.Client
var proxies map[string]*toxiproxy.Proxy
func init() {
var err error
toxiClient = toxiproxy.NewClient("localhost:8474")
proxies, err = toxiClient.Populate([]toxiproxy.Proxy{{
Name: "redis",
Listen: "localhost:26379",
Upstream: "localhost:6379",
}})
if err != nil {
panic(err)
}
// Alternatively, create the proxies manually with
// toxiClient.CreateProxy("redis", "localhost:26379", "localhost:6379")
}
func TestRedisBackendDown(t *testing.T) {
proxies["redis"].Disable()
defer proxies["redis"].Enable()
// Test that redis is down
_, err := redis.Dial("tcp", ":26379")
if err == nil {
t.Fatal("Connection to redis did not fail")
}
}
func TestRedisBackendSlow(t *testing.T) {
proxies["redis"].AddToxic("", "latency", "", 1, toxiproxy.Attributes{
"latency": 1000,
})
defer proxies["redis"].RemoveToxic("latency_downstream")
// Test that redis is slow
start := time.Now()
conn, err := redis.Dial("tcp", ":26379")
if err != nil {
t.Fatal("Connection to redis failed", err)
}
_, err = conn.Do("GET", "test")
if err != nil {
t.Fatal("Redis command failed", err)
} else if time.Since(start) < 900*time.Millisecond {
t.Fatal("Redis command did not take long enough:", time.Since(start))
}
}
func TestEphemeralProxy(t *testing.T) {
proxy, _ := toxiClient.CreateProxy("test", "", "google.com:80")
defer proxy.Delete()
// Test connection through proxy.Listen
resp, err := http.Get("http://" + proxy.Listen)
if err != nil {
t.Fatal(err)
} else if resp.StatusCode != 200 {
t.Fatal("Proxy to google failed:", resp.StatusCode)
}
}
```
|