diff --git a/v2/pkg/output/output.go b/v2/pkg/output/output.go index 3d3b8e847..a61d20ee3 100644 --- a/v2/pkg/output/output.go +++ b/v2/pkg/output/output.go @@ -11,6 +11,7 @@ import ( "time" "github.com/pkg/errors" + "go.uber.org/multierr" jsoniter "github.com/json-iterator/go" "github.com/logrusorgru/aurora" @@ -36,7 +37,7 @@ type Writer interface { // Write writes the event to file and/or screen. Write(*ResultEvent) error // WriteFailure writes the optional failure event for template to file and/or screen. - WriteFailure(event InternalEvent) error + WriteFailure(*InternalWrappedEvent) error // Request logs a request in the trace log Request(templateID, url, requestType string, err error) // WriteStoreDebugData writes the request/response debug data to file @@ -302,10 +303,26 @@ func (w *StandardWriter) Close() { } // WriteFailure writes the failure event for template to file and/or screen. -func (w *StandardWriter) WriteFailure(event InternalEvent) error { +func (w *StandardWriter) WriteFailure(wrappedEvent *InternalWrappedEvent) error { if !w.matcherStatus { return nil } + if len(wrappedEvent.Results) > 0 { + errs := []error{} + for _, result := range wrappedEvent.Results { + result.MatcherStatus = false // just in case + if err := w.Write(result); err != nil { + errs = append(errs, err) + } + } + if len(errs) > 0 { + return multierr.Combine(errs...) + } + return nil + } + // if no results were found, manually create a failure event + event := wrappedEvent.InternalEvent + templatePath, templateURL := utils.TemplatePathURL(types.ToString(event["template-path"])) var templateInfo model.Info if event["template-info"] != nil { @@ -319,6 +336,8 @@ func (w *StandardWriter) WriteFailure(event InternalEvent) error { Info: templateInfo, Type: types.ToString(event["type"]), Host: types.ToString(event["host"]), + Request: types.ToString(event["request"]), + Response: types.ToString(event["response"]), MatcherStatus: false, Timestamp: time.Now(), } diff --git a/v2/pkg/protocols/common/executer/executer.go b/v2/pkg/protocols/common/executer/executer.go index 8bfa1be0f..e40fa5c51 100644 --- a/v2/pkg/protocols/common/executer/executer.go +++ b/v2/pkg/protocols/common/executer/executer.go @@ -74,7 +74,7 @@ func (e *Executer) Execute(input *contextargs.Context) (bool, error) { var lastMatcherEvent *output.InternalWrappedEvent writeFailureCallback := func(event *output.InternalWrappedEvent, matcherStatus bool) { if !results.Load() && matcherStatus { - if err := e.options.Output.WriteFailure(event.InternalEvent); err != nil { + if err := e.options.Output.WriteFailure(event); err != nil { gologger.Warning().Msgf("Could not write failure event to output: %s\n", err) } results.CompareAndSwap(false, true) diff --git a/v2/pkg/templates/cluster.go b/v2/pkg/templates/cluster.go index d1c8caf10..72a835a79 100644 --- a/v2/pkg/templates/cluster.go +++ b/v2/pkg/templates/cluster.go @@ -250,7 +250,7 @@ func (e *ClusterExecuter) Execute(input *contextargs.Context) (bool, error) { event.InternalEvent["template-info"] = operator.templateInfo if result == nil && !matched { - if err := e.options.Output.WriteFailure(event.InternalEvent); err != nil { + if err := e.options.Output.WriteFailure(event); err != nil { gologger.Warning().Msgf("Could not write failure event to output: %s\n", err) } continue diff --git a/v2/pkg/testutils/testutils.go b/v2/pkg/testutils/testutils.go index 26ffe7000..2114eda8a 100644 --- a/v2/pkg/testutils/testutils.go +++ b/v2/pkg/testutils/testutils.go @@ -136,7 +136,7 @@ func (m *MockOutputWriter) Request(templateID, url, requestType string, err erro } // WriteFailure writes the event to file and/or screen. -func (m *MockOutputWriter) WriteFailure(result output.InternalEvent) error { +func (m *MockOutputWriter) WriteFailure(*output.InternalWrappedEvent) error { return nil } func (m *MockOutputWriter) WriteStoreDebugData(host, templateID, eventType string, data string) {