Skip to content
Permalink
Browse files

Add -config option for toxiproxy startup

  • Loading branch information
xthexder committed Dec 7, 2016
1 parent 8e40aad commit 46df58de01ccec4756ef3495aa1190eb1ea4dc49
Showing with 93 additions and 50 deletions.
  1. +18 −49 api.go
  2. +26 −0 cmd/toxiproxy.go
  3. +49 −1 proxy_collection.go
67 api.go
@@ -132,65 +132,27 @@ func (server *ApiServer) ProxyCreate(response http.ResponseWriter, request *http
}

func (server *ApiServer) Populate(response http.ResponseWriter, request *http.Request) {
input := []struct {
Proxy
Enabled *bool `json:"enabled"` // Overrides Proxy field to make field nullable
}{}
proxies, err := server.Collection.PopulateJson(request.Body)

err := json.NewDecoder(request.Body).Decode(&input)
if apiError(response, joinError(err, ErrBadRequestBody)) {
return
}

// Check for valid input before creating any proxies
t := true
for i, p := range input {
if len(p.Name) < 1 {
apiError(response, joinError(fmt.Errorf("name at proxy %d", i+1), ErrMissingField))
return
}
if len(p.Upstream) < 1 {
apiError(response, joinError(fmt.Errorf("upstream at proxy %d", i+1), ErrMissingField))
return
}
if p.Enabled == nil {
input[i].Enabled = &t
}
}

proxies := make([]proxyToxics, 0, len(input))

responseCode := http.StatusCreated
var apiErr *ApiError
for _, p := range input {
proxy := NewProxy()
proxy.Name = p.Name
proxy.Listen = p.Listen
proxy.Upstream = p.Upstream

err = server.Collection.AddOrReplace(proxy, *p.Enabled)
if err != nil {
var ok bool
apiErr, ok = err.(*ApiError)
if !ok {
logrus.Warn("Error did not include status code: ", err)
apiErr = &ApiError{err.Error(), http.StatusInternalServerError}
}
responseCode = apiErr.StatusCode
break
}

proxies = append(proxies, proxyWithToxics(proxy))
apiErr, ok := err.(*ApiError)
if !ok && err != nil {
logrus.Warn("Error did not include status code: ", err)
apiErr = &ApiError{err.Error(), http.StatusInternalServerError}
}

data, err := json.Marshal(struct {
*ApiError `json:",omitempty"`
Proxies []proxyToxics `json:"proxies"`
}{apiErr, proxies})
}{apiErr, proxiesWithToxics(proxies)})
if apiError(response, err) {
return
}

responseCode := http.StatusCreated
if apiErr != nil {
responseCode = apiErr.StatusCode
}

response.Header().Set("Content-Type", "application/json")
response.WriteHeader(responseCode)
_, err = response.Write(data)
@@ -453,3 +415,10 @@ func proxyWithToxics(proxy *Proxy) (result proxyToxics) {
result.Toxics = proxy.Toxics.GetToxicArray()
return
}

func proxiesWithToxics(proxies []*Proxy) (result []proxyToxics) {
for _, proxy := range proxies {
result = append(result, proxyWithToxics(proxy))
}
return
}
@@ -3,23 +3,49 @@ package main
import (
"flag"
"math/rand"
"os"
"time"

"github.com/Shopify/toxiproxy"
"github.com/Sirupsen/logrus"
)

var host string
var port string
var config string

func init() {
flag.StringVar(&host, "host", "localhost", "Host for toxiproxy's API to listen on")
flag.StringVar(&port, "port", "8474", "Port for toxiproxy's API to listen on")
flag.StringVar(&config, "config", "", "JSON file containing proxies to create on startup")
seed := flag.Int64("seed", time.Now().UTC().UnixNano(), "Seed for randomizing toxics with")
flag.Parse()
rand.Seed(*seed)
}

func main() {
server := toxiproxy.NewServer()
if len(config) > 0 {
file, err := os.Open(config)
if err != nil {
logrus.WithFields(logrus.Fields{
"config": config,
"error": err,
}).Error("Error reading config file")
} else {
proxies, err := server.Collection.PopulateJson(file)
if err != nil {
logrus.WithFields(logrus.Fields{
"config": config,
"error": err,
}).Error("Failed to populate proxies from file")
} else {
logrus.WithFields(logrus.Fields{
"config": config,
"proxies": len(proxies),
}).Info("Populated proxies from file")
}
}
}
server.Listen(host, port)
}
@@ -1,6 +1,11 @@
package toxiproxy

import "sync"
import (
"encoding/json"
"fmt"
"io"
"sync"
)

// ProxyCollection is a collection of proxies. It's the interface for anything
// to add and remove proxies from the toxiproxy instance. It's responsibilty is
@@ -61,6 +66,49 @@ func (collection *ProxyCollection) AddOrReplace(proxy *Proxy, start bool) error
return nil
}

func (collection *ProxyCollection) PopulateJson(data io.Reader) ([]*Proxy, error) {
input := []struct {
Proxy
Enabled *bool `json:"enabled"` // Overrides Proxy field to make field nullable
}{}

err := json.NewDecoder(data).Decode(&input)
if err != nil {
return nil, joinError(err, ErrBadRequestBody)
}

// Check for valid input before creating any proxies
t := true
for i, p := range input {
if len(p.Name) < 1 {
return nil, joinError(fmt.Errorf("name at proxy %d", i+1), ErrMissingField)
}
if len(p.Upstream) < 1 {
return nil, joinError(fmt.Errorf("upstream at proxy %d", i+1), ErrMissingField)
}
if p.Enabled == nil {
input[i].Enabled = &t
}
}

proxies := make([]*Proxy, 0, len(input))

for _, p := range input {
proxy := NewProxy()
proxy.Name = p.Name
proxy.Listen = p.Listen
proxy.Upstream = p.Upstream

err = collection.AddOrReplace(proxy, *p.Enabled)
if err != nil {
break
}

proxies = append(proxies, proxy)
}
return proxies, err
}

func (collection *ProxyCollection) Proxies() map[string]*Proxy {
collection.RLock()
defer collection.RUnlock()

0 comments on commit 46df58d

Please sign in to comment.
You can’t perform that action at this time.