From 030ddf22c17be9317a944b457d797949c5617945 Mon Sep 17 00:00:00 2001 From: Olha Yevtushenko Date: Tue, 31 Oct 2023 17:55:21 +0200 Subject: [PATCH] cloud, plz: add public detail and abort to events --- controllers/common.go | 2 +- controllers/k6_create.go | 19 ++++++------- controllers/k6_finish.go | 4 ++- controllers/k6_initialize.go | 6 +++- controllers/k6_start.go | 4 ++- controllers/testrun_controller.go | 2 +- pkg/cloud/types.go | 46 +++++++++++++++++-------------- 7 files changed, 47 insertions(+), 36 deletions(-) diff --git a/controllers/common.go b/controllers/common.go index 2a7ecbee..b409b4c6 100644 --- a/controllers/common.go +++ b/controllers/common.go @@ -46,7 +46,7 @@ func inspectTestRun(ctx context.Context, log logr.Logger, k6 v1alpha1.TestRunI, } // there should be only 1 initializer pod - if podList.Items[0].Status.Phase != "Succeeded" { + if podList.Items[0].Status.Phase != corev1.PodSucceeded && podList.Items[0].Status.Phase != corev1.PodFailed { log.Info("Waiting for initializing pod to finish") return } diff --git a/controllers/k6_create.go b/controllers/k6_create.go index f76b49c3..6123c6c5 100644 --- a/controllers/k6_create.go +++ b/controllers/k6_create.go @@ -40,14 +40,8 @@ func CreateJobs(ctx context.Context, log logr.Logger, k6 v1alpha1.TestRunI, r *T token, tokenReady, err = loadToken(ctx, log, r.Client, k6.GetSpec().Token, sOpts) if err != nil { // An error here means a very likely mis-configuration of the token. - // Consider updating status to error to let a user know quicker? + // TODO: update status to error to let a user know quicker log.Error(err, "A problem while getting token.") - - if v1alpha1.IsTrue(k6, v1alpha1.CloudTestRun) { - events := cloud.ErrorEvent(cloud.K6OperatorStartError).WithDetail(fmt.Sprintf("Failed to retrieve token: %v", err)) - cloud.SendTestRunEvents(r.k6CloudClient, k6.GetSpec().TestRunID, log, events) - } - return ctrl.Result{}, nil } if !tokenReady { @@ -58,9 +52,10 @@ func CreateJobs(ctx context.Context, log logr.Logger, k6 v1alpha1.TestRunI, r *T log.Info("Creating test jobs") if res, err = createJobSpecs(ctx, log, k6, r, token); err != nil { - if v1alpha1.IsTrue(k6, v1alpha1.CloudTestRun) { - events := cloud.ErrorEvent(cloud.K6OperatorStartError).WithDetail(fmt.Sprintf("Failed to create runner jobs: %v", err)) + events := cloud.ErrorEvent(cloud.K6OperatorStartError). + WithDetail(fmt.Sprintf("Failed to create runner jobs: %v", err)). + WithAbort() cloud.SendTestRunEvents(r.k6CloudClient, k6.GetSpec().TestRunID, log, events) } @@ -86,7 +81,11 @@ func createJobSpecs(ctx context.Context, log logr.Logger, k6 v1alpha1.TestRunI, } if err := r.Get(ctx, namespacedName, found); err == nil || !errors.IsNotFound(err) { - log.Info("Could not start a new test, Make sure you've deleted your previous run.") + if err == nil { + err = fmt.Errorf("job with the name %s exists; make sure you've deleted your previous run", namespacedName.Name) + } + + log.Info(err.Error()) return ctrl.Result{}, err } diff --git a/controllers/k6_finish.go b/controllers/k6_finish.go index 5082bf35..ce25cdb0 100644 --- a/controllers/k6_finish.go +++ b/controllers/k6_finish.go @@ -54,7 +54,9 @@ func FinishJobs(ctx context.Context, log logr.Logger, k6 v1alpha1.TestRunI, r *T log.Info(msg) if v1alpha1.IsTrue(k6, v1alpha1.CloudTestRun) && failed > 0 { - events := cloud.ErrorEvent(cloud.K6OperatorRunnerError).WithDetail(msg) + events := cloud.ErrorEvent(cloud.K6OperatorRunnerError). + WithDetail(msg). + WithAbort() cloud.SendTestRunEvents(r.k6CloudClient, k6.GetSpec().TestRunID, log, events) } diff --git a/controllers/k6_initialize.go b/controllers/k6_initialize.go index bef2e1e6..f74a4260 100644 --- a/controllers/k6_initialize.go +++ b/controllers/k6_initialize.go @@ -52,9 +52,13 @@ func RunValidations(ctx context.Context, log logr.Logger, k6 v1alpha1.TestRunI, inspectOutput, inspectReady, err := inspectTestRun(ctx, log, k6, r.Client) if err != nil { + // Cloud output test run is not created yet at this point, so sending + // events is possible only for PLZ test run. if v1alpha1.IsTrue(k6, v1alpha1.CloudPLZTestRun) { // This error won't allow to start a test so let k6 Cloud know of it - events := cloud.ErrorEvent(cloud.K6OperatorStartError).WithDetail(fmt.Sprintf("Failed to inspect the test script: %v", err)) + events := cloud.ErrorEvent(cloud.K6OperatorStartError). + WithDetail(fmt.Sprintf("Failed to inspect the test script: %v", err)). + WithAbort() cloud.SendTestRunEvents(r.k6CloudClient, k6.GetSpec().TestRunID, log, events) } diff --git a/controllers/k6_start.go b/controllers/k6_start.go index b497a7e0..3d8868cc 100644 --- a/controllers/k6_start.go +++ b/controllers/k6_start.go @@ -71,7 +71,9 @@ func StartJobs(ctx context.Context, log logr.Logger, k6 v1alpha1.TestRunI, r *Te // let's try this approach if time.Since(t).Minutes() > 5 { if v1alpha1.IsTrue(k6, v1alpha1.CloudTestRun) { - events := cloud.ErrorEvent(cloud.K6OperatorStartError).WithDetail("Creation of runner pods takes too long: perhaps, something is off with your configuration. Check if runner jobs and pods were created successfully.") + events := cloud.ErrorEvent(cloud.K6OperatorStartError). + WithDetail("Creation of runner pods takes too long: your configuration might be off. Check if runner jobs and pods were created successfully."). + WithAbort() cloud.SendTestRunEvents(r.k6CloudClient, k6.GetSpec().TestRunID, log, events) } } diff --git a/controllers/testrun_controller.go b/controllers/testrun_controller.go index 5e742ae6..029563a4 100644 --- a/controllers/testrun_controller.go +++ b/controllers/testrun_controller.go @@ -82,7 +82,7 @@ func (r *TestRunReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct func (r *TestRunReconciler) reconcile(ctx context.Context, req ctrl.Request, log logr.Logger, k6 v1alpha1.TestRunI) (ctrl.Result, error) { var err error - if v1alpha1.IsTrue(k6, v1alpha1.CloudPLZTestRun) { + if v1alpha1.IsTrue(k6, v1alpha1.CloudTestRun) { // bootstrap the client found, err := r.createClient(ctx, k6, log) if err != nil { diff --git a/pkg/cloud/types.go b/pkg/cloud/types.go index a2d048c9..74836123 100644 --- a/pkg/cloud/types.go +++ b/pkg/cloud/types.go @@ -76,10 +76,14 @@ type EventPayload struct { } type Event struct { - ErrorCode `json:"error_code,omitempty"` - Detail string `json:"error_detail,omitempty"` Origin `json:"origin,omitempty"` - Reason string `json:"reason,omitempty"` + ErrorCode `json:"error_code,omitempty"` + + // reason is used for abort events, + // while details are for any non-abort event + Reason string `json:"reason,omitempty"` + Detail string `json:"error_detail,omitempty"` + PublicDetail string `json:"error_detail_public,omitempty"` } type EventType string @@ -111,7 +115,8 @@ var ( OriginK6 = Origin("k6") ) -// WithDetail sets detail only for the 1st event +// WithDetail sets detail only for the 1st event. +// If it's abort, WithDetail sets reason field. func (e *Events) WithDetail(s string) *Events { if len(*e) == 0 { return e @@ -121,32 +126,31 @@ func (e *Events) WithDetail(s string) *Events { (*e)[0].Reason = s } else { (*e)[0].Detail = s + (*e)[0].PublicDetail = s } return e } -// WithAbort adds abortEvent if errorEvent already exists -// func (e *Events) WithAbort(s string) *Events { -// if len(*e) == 0 { -// return -// } - -// if (*e)[0].EventType == errorEvent { -// ae := EventPayload{ -// EventType: abort, -// } -// } -// return e -// } +// WithAbort adds abortEvent to errorEvent if it already exists. +func (e *Events) WithAbort() *Events { + if len(*e) == 0 { + return e + } -func AbortEvent(o Origin) *Events { - e := Events([]*EventPayload{{ + if (*e)[0].EventType == errorEvent { + *e = append(*e, AbortEvent(OriginUser)) + } + return e +} + +func AbortEvent(o Origin) *EventPayload { + e := &EventPayload{ EventType: abortEvent, Event: Event{ Origin: o, }, - }}) - return &e + } + return e } func ErrorEvent(ec ErrorCode) *Events {