diff --git a/pkg/loadtester/task_ngrinder.go b/pkg/loadtester/task_ngrinder.go index 998fe73a..f090f971 100644 --- a/pkg/loadtester/task_ngrinder.go +++ b/pkg/loadtester/task_ngrinder.go @@ -22,6 +22,7 @@ func init() { clone := metadata["clone"] username := metadata["username"] passwd := metadata["passwd"] + pollInterval := metadata["pollInterval"] if server == "" || clone == "" || username == "" || passwd == "" { return nil, errors.New("server, clone, username and passwd are required metadata") } @@ -38,27 +39,38 @@ func init() { if err != nil { return nil, errors.New("metadata auth provided is invalid, base64 encoded username:password required") } + interval, err := strconv.Atoi(pollInterval) + if err != nil { + interval = 1 + } + return &NGrinderTask{ TaskBase{canary, logger}, - baseUrl, cloneId, username, string(passwdDecoded), -1, 5, + baseUrl, cloneId, username, string(passwdDecoded), -1, time.Duration(interval), }, nil }) } type NGrinderTask struct { TaskBase - baseUrl *url.URL - cloneId int - username string - passwd string - testId int + // base url of ngrinder server, e.g. http://ngrinder:8080 + baseUrl *url.URL + // template test to clone from + cloneId int + // http basic auth + username string + passwd string + // current ngrinder test id + testId int + // task status polling interval pollInterval time.Duration } func (task *NGrinderTask) Hash() string { - return hash(task.canary + task.CloneAndStartEndpoint().String()) + return hash(task.canary + string(task.cloneId)) } +// nGrinder REST endpoints func (task *NGrinderTask) CloneAndStartEndpoint() *url.URL { path, _ := url.Parse(fmt.Sprintf("perftest/api/%d/clone_and_start", task.cloneId)) return task.baseUrl.ResolveReference(path) @@ -72,6 +84,7 @@ func (task *NGrinderTask) StopEndpoint() *url.URL { return task.baseUrl.ResolveReference(path) } +// initiate a clone_and_start request and get new test id from response func (task *NGrinderTask) Run(ctx context.Context) bool { url := task.CloneAndStartEndpoint().String() result, err := task.request("POST", url, ctx) @@ -88,6 +101,7 @@ func (task *NGrinderTask) String() string { return task.canary + task.CloneAndStartEndpoint().String() } +// polling execution status of the new test and check if finished func (task *NGrinderTask) PollStatus(ctx context.Context) bool { // wait until ngrinder test finished/canceled or timedout tickChan := time.NewTicker(time.Second * task.pollInterval).C @@ -116,15 +130,20 @@ func (task *NGrinderTask) PollStatus(ctx context.Context) bool { } } +// send request, handle error, and eavl response json func (task *NGrinderTask) request(method, url string, ctx context.Context) (map[string]interface{}, error) { + task.logger.Debugf("send %s request to %s", method, url) req, _ := http.NewRequest(method, url, nil) req.SetBasicAuth(task.username, task.passwd) if ctx != nil { req = req.WithContext(ctx) } resp, err := http.DefaultClient.Do(req) - defer resp.Body.Close() + if resp != nil { + defer resp.Body.Close() + } if err != nil { + task.logger.Errorf("bad request: %s", err.Error()) return nil, err } respBytes, err := ioutil.ReadAll(resp.Body)