This is the Go client library for the Toxiproxy API. Please read the usage section in the Toxiproxy README before attempting to use the client.
This client is compatible with Toxiproxy 2.x, for the latest 1.x client see v1.2.1.
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 usingproxy.Save()
.- Proxies can be created in a single call using
client.CreateProxy()
. proxy.Disable()
andproxy.Enable()
have been added to simplify taking down a proxy.proxy.ToxicsUpstream
andproxy.ToxicsDownstream
have been merged into a singleActiveToxics
list.- `proxy.Toxics()`` no longer requires a direction to be specified, and will return toxics for both directions.
proxy.SetToxic()
has been replaced byproxy.AddToxic()
,proxy.UpdateToxic()
, andproxy.RemoveToxic()
.
For detailed API docs please see the Godoc documentation.
First import toxiproxy and create a new client:
import toxiproxy "github.com/Shopify/toxiproxy/v2/client"
client := toxiproxy.NewClient("localhost:8474")
You can then create a new proxy using the client:
proxy, err := client.CreateProxy("redis", "localhost:26379", "localhost:6379")
if err != nil {
panic(err)
}
For large amounts of proxies, they can also be created using a configuration file:
var config []toxiproxy.Proxy
data, _ := ioutil.ReadFile("config.json")
json.Unmarshal(data, &config)
proxies, err = client.Populate(config)
[{
"name": "redis",
"listen": "localhost:26379",
"upstream": "localhost:6379"
}]
Toxics can be added as follows:
// 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()
:
proxy.Disable()
When a proxy is no longer needed, it can be cleaned up with Delete()
:
proxy.Delete()
import (
"net/http"
"testing"
"time"
toxiproxy "github.com/Shopify/toxiproxy/v2/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",
// note: you cannot set toxics here via ActiveToxics
}})
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)
}
}