diff --git a/.gitignore b/.gitignore index a67d4ac7..a1d1285d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ toxiproxy toxiproxy-server +toxiproxy-cli cli toxiproxy.test testing diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bae9a98..be0fd715 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,13 @@ -# 2.0.0 (Unreleased) +# 2.0.0rc2 (Unreleased) + +* Add CLI (`toxiproxy-cli`) and rename server binary to `toxiproxy-server` #93 +* Fix removing a timeout toxic causing API to hang #89 +* API and client return toxics as array rather than a map of name to toxic #92 +* Fix multiple latency toxics not accumulating #94 +* Change default toxic name to `_` #96 +* Nest toxic attributes rather than having a flat structure #98 + +# 2.0.0rc1 (Unreleased) * 2.0 RFC: #54 and PR #62 * Change toxic API endpoints to an Add/Update/Remove structure @@ -14,8 +23,6 @@ * Make `ChanReader` in the `stream` package interruptible #77 * Define proxy buffer sizes per-toxic (Fixes #72) * Fix slicer toxic testing race condition #71 -* API and client return toxics as array rather than a map of name to toxic #92 -* Nest toxic attributes rather than having a flat structure #98 # 1.2.1 @@ -27,7 +34,6 @@ * Add `Dockerfile` * Fix latency toxic limiting bandwidth #67 * Add Slicer toxic -* Add CLI # 1.1.0 diff --git a/Makefile b/Makefile index 74467a74..b520fd65 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ -NAME=toxiproxy +SERVER_NAME=toxiproxy-server +CLI_NAME=toxiproxy-cli VERSION=$(shell cat VERSION) -DEB=pkg/$(NAME)_$(VERSION)_amd64.deb +DEB=pkg/toxiproxy_$(VERSION)_amd64.deb GODEP_PATH=$(shell pwd)/Godeps/_workspace ORIGINAL_PATH=$(shell echo $(GOPATH)) COMBINED_GOPATH=$(GODEP_PATH):$(ORIGINAL_PATH) @@ -8,44 +9,46 @@ COMBINED_GOPATH=$(GODEP_PATH):$(ORIGINAL_PATH) .PHONY: packages deb test linux darwin windows build: - GOPATH=$(COMBINED_GOPATH) go build -ldflags="-X github.com/Shopify/toxiproxy.Version=git-$(shell git rev-parse --short HEAD)" -o $(NAME) ./cmd + GOPATH=$(COMBINED_GOPATH) go build -ldflags="-X github.com/Shopify/toxiproxy.Version=git-$(shell git rev-parse --short HEAD)" -o $(SERVER_NAME) ./cmd + GOPATH=$(COMBINED_GOPATH) go build -ldflags="-X github.com/Shopify/toxiproxy.Version=git-$(shell git rev-parse --short HEAD)" -o $(CLI_NAME) ./cli all: deb linux darwin windows deb: $(DEB) -darwin: tmp/build/toxiproxy-server-darwin-amd64 tmp/build/toxiproxy-client-darwin-amd64 -linux: tmp/build/toxiproxy-server-linux-amd64 tmp/build/toxiproxy-client-linux-amd64 -windows: tmp/build/toxiproxy-server-windows-amd64.exe tmp/build/toxiproxy-client-windows-amd64.exe +darwin: tmp/build/$(SERVER_NAME)-darwin-amd64 tmp/build/$(CLI_NAME)-darwin-amd64 +linux: tmp/build/$(SERVER_NAME)-linux-amd64 tmp/build/$(CLI_NAME)-linux-amd64 +windows: tmp/build/$(SERVER_NAME)-windows-amd64.exe tmp/build/$(CLI_NAME)-windows-amd64.exe release: all docker clean: rm -f tmp/build/* - #rm -f $(NAME) + rm -f $(SERVER_NAME) + rm -f $(CLI_NAME) rm -f *.deb test: GOMAXPROCS=4 GOPATH=$(COMBINED_GOPATH) go test -v -race ./... -tmp/build/toxiproxy-server-linux-amd64: +tmp/build/$(SERVER_NAME)-linux-amd64: GOOS=linux GOARCH=amd64 GOPATH=$(COMBINED_GOPATH) go build -ldflags="-X github.com/Shopify/toxiproxy.Version=$(VERSION)" -o $(@) ./cmd -tmp/build/toxiproxy-server-darwin-amd64: +tmp/build/$(SERVER_NAME)-darwin-amd64: GOOS=darwin GOARCH=amd64 GOPATH=$(COMBINED_GOPATH) go build -ldflags="-X github.com/Shopify/toxiproxy.Version=$(VERSION)" -o $(@) ./cmd -tmp/build/toxiproxy-server-windows-amd64.exe: +tmp/build/$(SERVER_NAME)-windows-amd64.exe: GOOS=windows GOARCH=amd64 GOPATH=$(COMBINED_GOPATH) go build -ldflags="-X github.com/Shopify/toxiproxy.Version=$(VERSION)" -o $(@) ./cmd -tmp/build/toxiproxy-client-linux-amd64: +tmp/build/$(CLI_NAME)-linux-amd64: GOOS=linux GOARCH=amd64 GOPATH=$(COMBINED_GOPATH) go build -ldflags="-X github.com/Shopify/toxiproxy.Version=$(VERSION)" -o $(@) ./cli -tmp/build/toxiproxy-client-darwin-amd64: +tmp/build/$(CLI_NAME)-darwin-amd64: GOOS=darwin GOARCH=amd64 GOPATH=$(COMBINED_GOPATH) go build -ldflags="-X github.com/Shopify/toxiproxy.Version=$(VERSION)" -o $(@) ./cli -tmp/build/toxiproxy-client-windows-amd64.exe: +tmp/build/$(CLI_NAME)-windows-amd64.exe: GOOS=windows GOARCH=amd64 GOPATH=$(COMBINED_GOPATH) go build -ldflags="-X github.com/Shopify/toxiproxy.Version=$(VERSION)" -o $(@) ./cli -$(DEB): tmp/build/toxiproxy-server-linux-amd64 tmp/build/toxiproxy-client-linux-amd64 +$(DEB): tmp/build/$(SERVER_NAME)-linux-amd64 tmp/build/$(CLI_NAME)-linux-amd64 fpm -t deb \ -s dir \ -p tmp/build/ \ @@ -59,8 +62,8 @@ $(DEB): tmp/build/toxiproxy-server-linux-amd64 tmp/build/toxiproxy-client-linux- --description "TCP proxy to simulate network and system conditions" \ --url "https://github.com/Shopify/toxiproxy" \ $(word 1,$^)=/usr/bin/toxiproxy \ - $(word 1,$^)=/usr/bin/toxiproxy-server \ - $(word 2,$^)=/usr/bin/toxiproxy-client \ + $(word 1,$^)=/usr/bin/$(SERVER_NAME) \ + $(word 2,$^)=/usr/bin/$(CLI_NAME) \ ./share/toxiproxy.conf=/etc/init/toxiproxy.conf docker: diff --git a/README.md b/README.md index ee6b0690..4414751e 100644 --- a/README.md +++ b/README.md @@ -58,9 +58,9 @@ stopping you from creating a client in any other language (see 1. [Proxy fields](#proxy-fields) 2. [Toxic fields](#toxic-fields) 3. [Endpoints](#endpoints) - 4. [Curl example](#curl-example) -7. [FAQ](#frequently-asked-questions) -8. [Development](#development) +7. [CLI example](#cli-example) +8. [FAQ](#frequently-asked-questions) +9. [Development](#development) ## Why yet another chaotic TCP proxy? @@ -225,7 +225,7 @@ $ docker run -it shopify/toxiproxy If you have Go installed, you can build Toxiproxy from source using the make file: ```bash $ make build -$ ./toxiproxy +$ ./toxiproxy-server ``` #### Upgrading from Toxiproxy 1.x @@ -268,10 +268,10 @@ This code needs to run as early in boot as possible, before any code establishes a connection through Toxiproxy. Please check your client library for documentation on the population helpers. -Alternatively use the HTTP API directly to create proxies, e.g.: +Alternatively use the CLI to create proxies, e.g.: ```bash -curl -i -d '{"name": "shopify_test_redis_master", "upstream": "localhost:6379", "listen": "localhost:26379"}' localhost:8474/proxies +toxiproxy-cli create shopify_test_redis_master -l localhost:26379 -u localhost:6379 ``` We recommend a naming such as the above: `___`. @@ -309,6 +309,12 @@ Toxiproxy[:shopify_test_redis_master].downstream(:latency, latency: 1000).apply end ``` +Or via the CLI: + +```bash +toxiproxy-cli toxic add shopify_test_redis_master -t latency -a latency=1000 +``` + Please consult your respective client library on usage. ### Toxics @@ -426,16 +432,17 @@ All endpoints are JSON. - **POST /reset** - Enable all proxies and remove all active toxics - **GET /version** - Returns the server version number -### Curl Example +### CLI Example ```bash -$ curl -i -d '{"name": "redis", "upstream": "localhost:6379", "listen": "localhost:26379"}' localhost:8474/proxies -HTTP/1.1 201 Created -Content-Type: application/json -Date: Fri, 18 Mar 2016 01:19:59 GMT -Content-Length: 98 - -{"name":"redis","listen":"127.0.0.1:26379","upstream":"localhost:6379","enabled":true,"toxics":[]} +$ toxiproxy-cli create redis -l localhost:26379 -u localhost:6379 +Created new proxy redis +$ toxiproxy-cli list +Listen Upstream Name Enabled Toxics +====================================================================== +127.0.0.1:26379 localhost:6379 redis true None + +Hint: inspect toxics with `toxiproxy-client inspect ` ``` ```bash @@ -447,23 +454,8 @@ OK ``` ```bash -$ curl -i localhost:8474/proxies -HTTP/1.1 200 OK -Content-Type: application/json -Date: Fri, 18 Mar 2016 01:20:31 GMT -Content-Length: 108 - -{"redis":{"name":"redis","listen":"127.0.0.1:26379","upstream":"localhost:6379","enabled":true,"toxics":[]}} -``` - -```bash -$ curl -i -d '{"type":"latency", "attributes":{"latency":1000}}' localhost:8474/proxies/redis/toxics -HTTP/1.1 200 OK -Content-Type: application/json -Date: Fri, 18 Mar 2016 01:21:08 GMT -Content-Length: 122 - -{"attributes":{"latency":1000,"jitter":0},"name":"latency_downstream","type":"latency","stream":"downstream","toxicity":1} +$ toxiproxy-cli toxic add redis -t latency -a latency=1000 +Added downstream latency toxic 'latency_downstream' on proxy 'redis' ``` ```bash @@ -477,9 +469,8 @@ $ redis-cli -p 26379 ``` ```bash -$ curl -i -X DELETE localhost:8474/proxies/redis/toxics/latency_downstream -HTTP/1.1 204 No Content -Date: Fri, 18 Mar 2016 01:21:58 GMT +$ toxiproxy-cli toxic remove redis -n latency_downstream +Removed toxic 'latency_downstream' on proxy 'redis' ``` ```bash @@ -489,9 +480,8 @@ $ redis-cli -p 26379 ``` ```bash -$ curl -i -X DELETE localhost:8474/proxies/redis -HTTP/1.1 204 No Content -Date: Fri, 18 Mar 2016 01:22:20 GMT +$ toxiproxy-cli delete redis +Deleted proxy redis ``` ```bash diff --git a/VERSION b/VERSION index 4111d137..41ab234f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0.0rc1 +2.0.0rc2 diff --git a/cli/cli.go b/cli/cli.go index 60b70ac8..b7b5108a 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -5,6 +5,7 @@ import ( "strconv" "strings" + toxiproxyServer "github.com/Shopify/toxiproxy" "github.com/Shopify/toxiproxy/client" "github.com/codegangsta/cli" @@ -41,52 +42,46 @@ var toxicDescription = ` average_size=,size_variation=,delay= toxic add: - usage: toxiproxy-client add --type --toxicName \ + usage: toxiproxy-cli add --type --toxicName \ --attributes --upstream --downstream - example: toxiproxy-client toxic add myProxy -t latency -n myToxic -f latency=100,jitter=50 + example: toxiproxy-cli toxic add myProxy -t latency -n myToxic -f latency=100,jitter=50 toxic update: - usage: toxiproxy-client update --toxicName \ + usage: toxiproxy-cli update --toxicName \ --attributes - - example: toxiproxy-client toxic update myProxy -n myToxic -f jitter=25 - + + example: toxiproxy-cli toxic update myProxy -n myToxic -f jitter=25 + toxic delete: - usage: toxiproxy-client update --toxicName + usage: toxiproxy-cli update --toxicName - example: toxiproxy-client toxic delete myProxy -n myToxic + example: toxiproxy-cli toxic delete myProxy -n myToxic ` func main() { toxiproxyClient := toxiproxy.NewClient("http://localhost:8474") app := cli.NewApp() - app.Name = "Toxiproxy" - app.Version = "2.0-alpha" // We're still improving the client ui. + app.Name = "toxiproxy-cli" + app.Version = toxiproxyServer.Version app.Usage = "Simulate network and system conditions" app.Commands = []cli.Command{ { Name: "list", - Usage: "list all proxies\n\tusage: 'toxiproxy-client list'\n", + Usage: "list all proxies\n\tusage: 'toxiproxy-cli list'\n", Aliases: []string{"l", "li", "ls"}, Action: withToxi(list, toxiproxyClient), }, { Name: "inspect", Aliases: []string{"i", "ins"}, - Usage: "inspect a single proxy\n\tusage: 'toxiproxy-client inspect '\n", + Usage: "inspect a single proxy\n\tusage: 'toxiproxy-cli inspect '\n", Action: withToxi(inspect, toxiproxyClient), }, - { - Name: "toggle", - Usage: "\ttoggle enabled status on a proxy\n\t\tusage: 'toxiproxy-client toggle '\n", - Aliases: []string{"tog"}, - Action: withToxi(toggle, toxiproxyClient), - }, { Name: "create", - Usage: "create a new proxy\n\tusage: 'toxiproxy-client create --listen --upstream '\n", + Usage: "create a new proxy\n\tusage: 'toxiproxy-cli create --listen --upstream '\n", Aliases: []string{"c", "new"}, Flags: []cli.Flag{ cli.StringFlag{ @@ -100,22 +95,29 @@ func main() { }, Action: withToxi(create, toxiproxyClient), }, + { + Name: "toggle", + Usage: "\ttoggle enabled status on a proxy\n\t\tusage: 'toxiproxy-cli toggle '\n", + Aliases: []string{"tog"}, + Action: withToxi(toggle, toxiproxyClient), + }, { Name: "delete", - Usage: "\tdelete a proxy\n\t\tusage: 'toxiproxy-client delete '\n", + Usage: "\tdelete a proxy\n\t\tusage: 'toxiproxy-cli delete '\n", Aliases: []string{"d"}, Action: withToxi(delete, toxiproxyClient), }, { Name: "toxic", Aliases: []string{"t"}, - Usage: "\tadd, remove or update a toxic\n\t\tusage: see 'toxiproxy-client toxic'\n", + Usage: "\tadd, remove or update a toxic\n\t\tusage: see 'toxiproxy-cli toxic'\n", Description: toxicDescription, Subcommands: []cli.Command{ { - Name: "add", - Aliases: []string{"a"}, - Usage: "add a new toxic", + Name: "add", + Aliases: []string{"a"}, + Usage: "add a new toxic", + ArgsUsage: "", Flags: []cli.Flag{ cli.StringFlag{ Name: "toxicName, n", @@ -145,9 +147,10 @@ func main() { Action: withToxi(addToxic, toxiproxyClient), }, { - Name: "update", - Aliases: []string{"u"}, - Usage: "update an enabled toxic", + Name: "update", + Aliases: []string{"u"}, + Usage: "update an enabled toxic", + ArgsUsage: "", Flags: []cli.Flag{ cli.StringFlag{ Name: "toxicName, n", @@ -165,9 +168,10 @@ func main() { Action: withToxi(updateToxic, toxiproxyClient), }, { - Name: "remove", - Aliases: []string{"r", "delete", "d"}, - Usage: "remove an enabled toxic", + Name: "remove", + Aliases: []string{"r", "delete", "d"}, + Usage: "remove an enabled toxic", + ArgsUsage: "", Flags: []cli.Flag{ cli.StringFlag{ Name: "toxicName, n", @@ -209,7 +213,7 @@ func list(c *cli.Context, t *toxiproxy.Client) { if len(proxyNames) == 0 { fmt.Printf("%sno proxies\n\n%s", redColor, noColor) - hint("create a proxy with `toxiproxy-client create`") + hint("create a proxy with `toxiproxy-cli create`") return } @@ -223,7 +227,7 @@ func list(c *cli.Context, t *toxiproxy.Client) { enabledColor(proxy.Enabled), proxy.Name, purpleColor, proxy.Enabled, redColor, numToxics, noColor) } fmt.Println() - hint("inspect a toxic with `toxiproxy-client inspect `") + hint("inspect toxics with `toxiproxy-cli inspect `") } func inspect(c *cli.Context, t *toxiproxy.Client) { proxyName := c.Args().First() @@ -265,7 +269,7 @@ func inspect(c *cli.Context, t *toxiproxy.Client) { } fmt.Println() - hint("add a toxic with `toxiproxy-client toxic add`") + hint("add a toxic with `toxiproxy-cli toxic add`") } func toggle(c *cli.Context, t *toxiproxy.Client) {