summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2021-03-24 00:39:55 +0700
committerShulhan <ms@kilabit.info>2021-03-24 00:39:55 +0700
commit896e55e6406b0837041c0aad75035f5839083e25 (patch)
tree81a059e9f22e4fe3a54d1296bd08806071b7bca6
parent5ffaf533cd7e4d26365b342f0f6d15bd8d1ff5d1 (diff)
downloadgorankusu-896e55e6406b0837041c0aad75035f5839083e25.tar.xz
all: move BaseUrl from AttackOptions to Target
The BaseUrl seems like not a good fit on AttackOptions since its should never changes, so we move it to the Target.
-rw-r--r--_www/index.js12
-rw-r--r--attack_options.go20
-rw-r--r--example/example.go12
-rw-r--r--http_target.go4
-rw-r--r--target.go34
-rw-r--r--trunks.go15
6 files changed, 52 insertions, 45 deletions
diff --git a/_www/index.js b/_www/index.js
index 2a94043..fd0f4d7 100644
--- a/_www/index.js
+++ b/_www/index.js
@@ -102,13 +102,15 @@ function renderTarget(targetID) {
}
w = `
<h2>${target.Name}</h2>
+
+ <div class="input">
+ <label> Base URL </label>:
+ <input id="BaseUrl" readonly="" value="${target.BaseUrl}"/>
+ </div>
+
<div class="AttackOpts">
<h3> Attack options </h3>
<div class="input">
- <label> Base URL </label>:
- <input id="BaseUrl" readonly="" value="${target.Opts.BaseUrl}"/>
- </div>
- <div class="input">
<label> Duration </label>:
<input id="Duration" value="${target.Opts.Duration / 1e9}"/>
</div>
@@ -333,7 +335,7 @@ async function attackResultDelete(name) {
let msg = `Are you sure you want to delete the result: ${name}?`
let yes = window.confirm(msg)
if (!yes) {
- return;
+ return
}
let url = "/_trunks/api/target/attack/result?name=" + name
diff --git a/attack_options.go b/attack_options.go
index 2b41b1e..fa0cf71 100644
--- a/attack_options.go
+++ b/attack_options.go
@@ -5,18 +5,12 @@
package trunks
import (
- "fmt"
"time"
vegeta "github.com/tsenart/vegeta/v12/lib"
)
type AttackOptions struct {
- // BaseUrl contains the target address that serve the service to
- // be tested.
- // This field is required.
- BaseUrl string `ini:"trunks:attack:base_url"`
-
// Duration define the duration for each attack to be executed,
// in seconds.
// For example, if the AttackRate is 500 and AttackDuration is 10
@@ -24,29 +18,24 @@ type AttackOptions struct {
// requests.
// This field is optional, default to DefaultAttackDuration if its
// zero.
- Duration time.Duration `ini:"trunks:attack:duration"`
+ Duration time.Duration
// RatePerSecond define the number of request per second.
// This field is optional, default to DefaultAttackRatePerSecond if
// its zero.
- RatePerSecond int `ini:"trunks:attack:rate_per_second"`
+ RatePerSecond int
ratePerSecond vegeta.Rate
// Timeout define the overall time to run the attack on each target.
// This field is optional, default to DefaultAttackTimeout if its
// zero.
- Timeout time.Duration `ini:"trunks:attack:timeout"`
+ Timeout time.Duration
}
-func (attackOpts *AttackOptions) init() (err error) {
- if len(attackOpts.BaseUrl) == 0 {
- return fmt.Errorf("AttackOptions.BaseUrl is not defined")
- }
-
+func (attackOpts *AttackOptions) init() {
if attackOpts.Timeout == 0 {
attackOpts.Timeout = DefaultAttackTimeout
}
-
if attackOpts.RatePerSecond == 0 {
attackOpts.RatePerSecond = DefaultAttackRatePerSecond
}
@@ -57,5 +46,4 @@ func (attackOpts *AttackOptions) init() (err error) {
if attackOpts.Duration == 0 {
attackOpts.Duration = DefaultAttackDuration
}
- return nil
}
diff --git a/example/example.go b/example/example.go
index 9a91ebb..b2ef46c 100644
--- a/example/example.go
+++ b/example/example.go
@@ -92,9 +92,9 @@ func (ex *Example) registerEndpoints() (err error) {
func (ex *Example) registerTargets() (err error) {
targetHttp := &trunks.Target{
- Name: "Example",
+ Name: "Example HTTP",
+ BaseUrl: fmt.Sprintf("http://%s", ex.trunks.Env.ListenAddress),
Opts: &trunks.AttackOptions{
- BaseUrl: fmt.Sprintf("http://%s", ex.trunks.Env.ListenAddress),
Duration: 300 * time.Second,
RatePerSecond: 1,
},
@@ -160,7 +160,7 @@ func (ex *Example) pathExamplePostForm(epr *libhttp.EndpointRequest) ([]byte, er
func (ex *Example) runExampleGet(req *trunks.RunRequest) ([]byte, error) {
if req.Target.HttpClient == nil {
- req.Target.HttpClient = libhttp.NewClient(req.Target.Opts.BaseUrl, nil, true)
+ req.Target.HttpClient = libhttp.NewClient(req.Target.BaseUrl, nil, true)
}
_, resbody, err := req.Target.HttpClient.Get(
req.HttpTarget.Path,
@@ -175,7 +175,7 @@ func (ex *Example) runExampleGet(req *trunks.RunRequest) ([]byte, error) {
func (ex *Example) preattackExampleGet(rr *trunks.RunRequest) {
ex.targetExampleGet = vegeta.Target{
Method: rr.HttpTarget.Method.String(),
- URL: fmt.Sprintf("%s%s", rr.Target.Opts.BaseUrl, rr.HttpTarget.Path),
+ URL: fmt.Sprintf("%s%s", rr.Target.BaseUrl, rr.HttpTarget.Path),
Header: rr.HttpTarget.Headers.ToHttpHeader(),
}
@@ -198,7 +198,7 @@ func (ex *Example) attackExampleGet(rr *trunks.RunRequest) vegeta.Targeter {
func (ex *Example) runExamplePostForm(req *trunks.RunRequest) ([]byte, error) {
if req.Target.HttpClient == nil {
- req.Target.HttpClient = libhttp.NewClient(req.Target.Opts.BaseUrl, nil, true)
+ req.Target.HttpClient = libhttp.NewClient(req.Target.BaseUrl, nil, true)
}
_, resbody, err := req.Target.HttpClient.PostForm(
req.HttpTarget.Path,
@@ -213,7 +213,7 @@ func (ex *Example) runExamplePostForm(req *trunks.RunRequest) ([]byte, error) {
func (ex *Example) preattackExamplePostForm(rr *trunks.RunRequest) {
ex.targetExamplePostForm = vegeta.Target{
Method: rr.HttpTarget.Method.String(),
- URL: fmt.Sprintf("%s%s", rr.Target.Opts.BaseUrl, rr.HttpTarget.Path),
+ URL: fmt.Sprintf("%s%s", rr.Target.BaseUrl, rr.HttpTarget.Path),
Header: rr.HttpTarget.Headers.ToHttpHeader(),
}
diff --git a/http_target.go b/http_target.go
index 5652df3..bb5c370 100644
--- a/http_target.go
+++ b/http_target.go
@@ -48,13 +48,13 @@ type HttpTarget struct {
Attack HttpAttackHandler `json:"-"`
PreAttack HttpPreAttackHandler `json:"-"`
AttackLocker sync.Mutex `json:"-"` // Use this inside the Attack to lock resource.
- Status string
// Results contains list of load testing output.
Results []*AttackResult
// AllowAttack if its true the "Attack" button will be showed on user
- // interface to allow client to run load testing on this HttpTarget.
+ // interface and client will be allowed to run load testing on this
+ // HttpTarget.
AllowAttack bool
}
diff --git a/target.go b/target.go
index 1be9f90..3d0be3f 100644
--- a/target.go
+++ b/target.go
@@ -14,11 +14,18 @@ import (
// Target contains group of HttpTarget that can be tested by Trunks.
//
type Target struct {
- ID string
- Name string
- Opts *AttackOptions
- Vars KeyValue
- HttpTargets []*HttpTarget
+ ID string
+ Name string
+
+ // BaseUrl contains the target address that serve the service to
+ // be tested.
+ // This field is required.
+ BaseUrl string
+
+ Opts *AttackOptions
+ Vars KeyValue
+ HttpTargets []*HttpTarget
+ WebSocketTargets []*WebSocketTarget
// HttpClient that can be used for running HttpTarget.
HttpClient *libhttp.Client `json:"-"`
@@ -28,6 +35,9 @@ func (target *Target) init() (err error) {
if len(target.Name) == 0 {
return fmt.Errorf("Target.Name is empty")
}
+ if len(target.BaseUrl) == 0 {
+ return fmt.Errorf("Target.BaseUrl is not defined")
+ }
target.ID = generateID(target.Name)
@@ -35,10 +45,7 @@ func (target *Target) init() (err error) {
target.Opts = &AttackOptions{}
}
- err = target.Opts.init()
- if err != nil {
- return err
- }
+ target.Opts.init()
if target.Vars == nil {
target.Vars = KeyValue{}
@@ -59,3 +66,12 @@ func (target *Target) getHttpTargetByID(id string) *HttpTarget {
}
return nil
}
+
+func (target *Target) getWebSocketTargetByID(id string) (wst *WebSocketTarget) {
+ for _, wst = range target.WebSocketTargets {
+ if wst.ID == id {
+ return wst
+ }
+ }
+ return nil
+}
diff --git a/trunks.go b/trunks.go
index bc95a42..7f36e7d 100644
--- a/trunks.go
+++ b/trunks.go
@@ -117,7 +117,7 @@ func (trunks *Trunks) RegisterTarget(target *Target) (err error) {
//
func (trunks *Trunks) Start() (err error) {
mlog.Outf("trunks: scanning previous attack results...\n")
- trunks.scanAttackResults()
+ trunks.scanResultsDir()
mlog.Outf("trunks: starting attack worker...\n")
go trunks.workerAttackQueue()
@@ -285,7 +285,7 @@ func (trunks *Trunks) apiTargetAttack(epr *libhttp.EndpointRequest) (resbody []b
trunks.attackq <- req
msg := fmt.Sprintf("Attacking %s/%s with %d RPS for %s seconds",
- req.Target.Opts.BaseUrl, req.HttpTarget.Path,
+ req.Target.BaseUrl, req.HttpTarget.Path,
req.Target.Opts.RatePerSecond, req.Target.Opts.Duration)
mlog.Outf("%s: %s\n", logp, msg)
@@ -453,13 +453,14 @@ func (trunks *Trunks) getTargetByResultFilename(name string) (t *Target, ht *Htt
}
//
-// scanAttackResults scan the environment's ResultsDir for past attack results
-// and add it to each target based on ID.
-// Due to size of output can be big (maybe more than 5000 records), this
+// scanResultsDir scan the environment's ResultsDir for the past attack
+// results and add it to each target based on ID on file name.
+//
+// Due to size of file can be big (maybe more than 5000 records), this
// function only parse the file name and append it to Results field.
//
-func (trunks *Trunks) scanAttackResults() {
- logp := "scanAttackResults"
+func (trunks *Trunks) scanResultsDir() {
+ logp := "scanResultsDir"
dir, err := os.Open(trunks.Env.ResultsDir)
if err != nil {