commit 5ffbb047b3b42105f40d5ad45d56e74e0e41332f Author: Mason Payne Date: Sun Jul 18 14:07:08 2021 -0600 save this stuff diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ef516f4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +load-testing.exe diff --git a/load.sh b/load.sh new file mode 100644 index 0000000..32d0759 --- /dev/null +++ b/load.sh @@ -0,0 +1,132 @@ +for i in {0..35} +do +curl -s --location --request GET 'https://dev.bergx.io/api/v1/apps/users?[1-1000]' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6IiIsImNsaWVudElkIjoiNTBiMmFiNjEtODllNy00MmQ3LTgxOWYtMzRjYTkzYjRlYTliIiwidXNlcklkIjoiIiwidHlwZSI6ImFjY2Vzc1Rva2VuIiwiaWF0IjoxNTg4MDUzNDMxLCJleHAiOjE1ODgwNTUyMzF9.241Bs1XlRMJAGlUOxQ5ZC1gLeZ8a5QmfpzhjV4yTF3w' \ +--data-raw '' -o nul & +pidlist="$pidlist $!" +curl --location --request PUT 'https://dev.bergx.io/api/v1/apps/users/b9578a59-fa2d-40d8-ae35-4df92238c1f3?[1-100]' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6IiIsImNsaWVudElkIjoiNTBiMmFiNjEtODllNy00MmQ3LTgxOWYtMzRjYTkzYjRlYTliIiwidXNlcklkIjoiIiwidHlwZSI6ImFjY2Vzc1Rva2VuIiwiaWF0IjoxNTg4MDUzNDMxLCJleHAiOjE1ODgwNTUyMzF9.241Bs1XlRMJAGlUOxQ5ZC1gLeZ8a5QmfpzhjV4yTF3w' \ +--header 'Content-Type: text/plain' \ +--data-raw '{ + "claims": { + "email": "gomas.bmw@gmail.com", + "sub": "b9578a59-fa2d-40d8-ae35-4df92238c1f3", + "email_verified": true, + "gender": "male", + "picture": "https://upload.wikimedia.org/wikipedia/commons/e/e8/CandymyloveYasu.png", + "family_name": "Payne", + "birthdate": "1987-12-22" + }, + "organizations": [], + "orgAutho": {}, + "app": "637d6e72-c773-4229-9cb5-4813b0c546e6" +}' -s -o nul & +done + +# for i in {0..60} +# do +# curl -s --location --request GET 'http://192.168.1.69:8080/api/v1/apps/users?[1-1000]' \ +# --header 'Content-Type: application/json' \ +# --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6IiIsImNsaWVudElkIjoiNTBiMmFiNjEtODllNy00MmQ3LTgxOWYtMzRjYTkzYjRlYTliIiwidXNlcklkIjoiIiwidHlwZSI6ImFjY2Vzc1Rva2VuIiwiaWF0IjoxNTg4MDUyMzMwLCJleHAiOjE1ODgwNTQxMzB9.jmBvBr7G2wYMX9efdGZO24RJJQrYZts3y2iAa18MZ8Q' \ +# --data-raw '' -o nul & +# pidlist="$pidlist $!" +# done + +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" +# curl -s "https://dev.bergx.io/auth/login?[1-100]" -o nul & +# pidlist="$pidlist $!" + + +for job in $pidlist +do + echo $job + wait $job || let "FAIL+=1" +done + +if [ "$FAIL" == "0" ]; then + echo "YAY!" +else + echo "FAIL! ($FAIL)" +fi diff --git a/main.go b/main.go new file mode 100644 index 0000000..381de55 --- /dev/null +++ b/main.go @@ -0,0 +1,138 @@ +package main + +import ( + "fmt" + "log" + "net/http" + "os" + "time" + + "github.com/urfave/cli" +) + +var app *cli.App + +func main() { + app = &cli.App{ + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "method", + Aliases: []string{"m"}, + Value: "GET", + Usage: "The `METHOD` for making the request", + }, + &cli.DurationFlag{ + Name: "duration", + Aliases: []string{"d"}, + Value: time.Second * 60, + Usage: "`DURATION` for how long to run the test", + }, + &cli.Int64Flag{ + Name: "rpm", + Usage: "`RATE-PER-MINUTE`", + Value: 60, + }, + &cli.StringSliceFlag{ + Name: "request", + Aliases: []string{"r"}, + Value: cli.NewStringSlice("http://localhost:8080/"), + Usage: "The `URL` for making the request", + }, + &cli.StringSliceFlag{ + Name: "header", + Aliases: []string{"H"}, + Value: cli.NewStringSlice("Content-Type: application/json"), + Usage: "The `HEADER` for the request", + }, + }, + Name: "Burst CLI", + Usage: "Run Burst to throw large amounts of traffic at a give url or set of urls", + UsageText: "burst -m GET -r http://localhost:8080/ -H 'Content-Type: application/json' -o data.json --rpm 1000", + Action: func(c *cli.Context) error { + fmt.Println("Bursting with happiness") + process(c) + return nil + }, + EnableBashCompletion: true, + Version: "1.0.0", + } + + err := app.Run(os.Args) + if err != nil { + log.Fatal(err) + } +} + +func request(ctx *cli.Context, i int) (*http.Response, error) { + req := ctx.StringSlice("request") + var resp *http.Response + method := ctx.String("method") + if method == "GET" { + resp, err := http.Get(req[i]) + if err != nil { + log.Fatal(err) + } + fmt.Println(resp.Body) + } + // if method == "POST" { + // resp, err := http.POST(req[i]) + // if err != nil { + // log.Fatal(err) + // } + // fmt.Println(resp.Body) + // } + return resp, nil +} + +func process(ctx *cli.Context) error { + req := ctx.StringSlice("request") + ticker := time.NewTicker(500 * time.Millisecond) + done := make(chan bool, len(req)) + + go func() { + for { + for { + select { + case <-done: + return + case t := <-ticker.C: + fmt.Println(req[0]) + resp, err := request(ctx, 0) + if err != nil { + log.Fatal(err) + } + fmt.Println(resp.Body) + fmt.Println("Tick at", t) + } + } + } + }() + + time.Sleep(ctx.Duration("duration")) + done <- true + + // select { + // case <-ch: + // fmt.Println("Read from ch") + // case <-time.After(1 * time.Second): + // fmt.Println("Timed out") + // } + + // if method == "POST" { + // resp, err := http.POST(req, data) + // if err != nil { + // log.Fatal(err) + // return err + // } + // } + + // if method == "PUT" { + // resp, err := http.Get(req) + // if err != nil { + // log.Fatal(err) + // return err + // } + // } + + return nil +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..7b99d2c --- /dev/null +++ b/readme.md @@ -0,0 +1,44 @@ +# Burst + +A simple CLI tool for load testing specific endpoints. + +Or just try this: http://servermonitoringhq.com/blog/how_to_quickly_stress_test_a_web_server + +### Usage + +```bash +burst --request GET 'https://dev.bergx.io/api/v1/apps/users' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer {{authtoken}}' \ +--out data.json \ +--rate max +``` + +Which is similar to: +```bash +curl --location --request GET '192.168.1.69:8080/api/v1/apps/users' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer {{authtoken}}' \ +--data-raw '' +``` + +### Options + +`-r | --request method url` specifies the method type for the request and the url to test. + +`-H | --header` will allow you to attach any headers to your request. + +`-o path | --out path` specifies the output file for data gathered. + +`-c path | --config path` specifies the file for a configured test. + + +### Config file + +In the config file you can specify many requests and the rate at which to test them. + +```json +{ + "": "" +} +```