diff options
| author | Shulhan <ms@kilabit.info> | 2021-03-24 00:39:55 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2021-03-24 00:39:55 +0700 |
| commit | 896e55e6406b0837041c0aad75035f5839083e25 (patch) | |
| tree | 81a059e9f22e4fe3a54d1296bd08806071b7bca6 | |
| parent | 5ffaf533cd7e4d26365b342f0f6d15bd8d1ff5d1 (diff) | |
| download | gorankusu-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.js | 12 | ||||
| -rw-r--r-- | attack_options.go | 20 | ||||
| -rw-r--r-- | example/example.go | 12 | ||||
| -rw-r--r-- | http_target.go | 4 | ||||
| -rw-r--r-- | target.go | 34 | ||||
| -rw-r--r-- | trunks.go | 15 |
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 } @@ -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 +} @@ -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 { |
