Skip to content

Commit

Permalink
cloud, plz: add public detail and abort to events
Browse files Browse the repository at this point in the history
  • Loading branch information
yorugac committed Nov 21, 2023
1 parent 2e8a5b8 commit 0584c40
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 42 deletions.
11 changes: 11 additions & 0 deletions api/v1alpha1/testruni.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,14 @@ type TestRunI interface {
GetSpec() *TestRunSpec
NamespacedName() types.NamespacedName
}

// TestRunID is a tiny helper to get k6 Cloud test run ID.
// PLZ test run will have test run ID as part of spec
// while cloud output test run as part of status.
func TestRunID(k6 TestRunI) string {
specId := k6.GetSpec().TestRunID
if len(specId) > 0 {
return specId
}
return k6.GetStatus().TestRunID
}
2 changes: 1 addition & 1 deletion controllers/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
21 changes: 10 additions & 11 deletions controllers/k6_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -58,10 +52,11 @@ 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))
cloud.SendTestRunEvents(r.k6CloudClient, k6.GetSpec().TestRunID, log, events)
events := cloud.ErrorEvent(cloud.K6OperatorStartError).
WithDetail(fmt.Sprintf("Failed to create runner jobs: %v", err)).
WithAbort()
cloud.SendTestRunEvents(r.k6CloudClient, v1alpha1.TestRunID(k6), log, events)
}

return res, err
Expand All @@ -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
}

Expand Down
6 changes: 4 additions & 2 deletions controllers/k6_finish.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,10 @@ 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)
cloud.SendTestRunEvents(r.k6CloudClient, k6.GetSpec().TestRunID, log, events)
events := cloud.ErrorEvent(cloud.K6OperatorRunnerError).
WithDetail(msg).
WithAbort()
cloud.SendTestRunEvents(r.k6CloudClient, v1alpha1.TestRunID(k6), log, events)
}

if finished < k6.GetSpec().Parallelism {
Expand Down
8 changes: 6 additions & 2 deletions controllers/k6_initialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,14 @@ 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))
cloud.SendTestRunEvents(r.k6CloudClient, k6.GetSpec().TestRunID, log, events)
events := cloud.ErrorEvent(cloud.K6OperatorStartError).
WithDetail(fmt.Sprintf("Failed to inspect the test script: %v", err)).
WithAbort()
cloud.SendTestRunEvents(r.k6CloudClient, v1alpha1.TestRunID(k6), log, events)
}

// inspectTestRun made a log message already so just return without requeue
Expand Down
6 changes: 4 additions & 2 deletions controllers/k6_start.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,10 @@ 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.")
cloud.SendTestRunEvents(r.k6CloudClient, k6.GetSpec().TestRunID, log, events)
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, v1alpha1.TestRunID(k6), log, events)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion controllers/testrun_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions pkg/cloud/test_runs.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ func GetTestRunData(client *cloudapi.Client, refID string) (*TestRunData, error)
return getTestRun(client, url)
}

// called by K6 controller
// called by TestRun controller
func GetTestRunState(client *cloudapi.Client, refID string, log logr.Logger) (TestRunStatus, error) {
url := fmt.Sprintf("%s/loadtests/v4/test_runs(%s)?$select=id,run_status", ApiURL(client.BaseURL()), refID)
trData, err := getTestRun(client, url)
Expand All @@ -121,7 +121,7 @@ func GetTestRunState(client *cloudapi.Client, refID string, log logr.Logger) (Te
return TestRunStatus(trData.RunStatus), nil
}

// called by K6 controller
// called by TestRun controller
// If there's an error, it'll be logged.
func SendTestRunEvents(client *cloudapi.Client, refID string, log logr.Logger, events *Events) {
if len(*events) == 0 {
Expand Down
46 changes: 25 additions & 21 deletions pkg/cloud/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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 {
Expand Down

0 comments on commit 0584c40

Please sign in to comment.