@@ -15,6 +15,7 @@ import (
1515 "github.com/keptn/go-utils/pkg/api/models"
1616 "github.com/keptn/go-utils/pkg/common/strutils"
1717 "github.com/keptn/go-utils/pkg/lib/keptn"
18+ "github.com/sirupsen/logrus"
1819
1920 ceObs "github.com/cloudevents/sdk-go/observability/opentelemetry/v2/client"
2021 ceObsHttp "github.com/cloudevents/sdk-go/observability/opentelemetry/v2/http"
@@ -23,6 +24,14 @@ import (
2324 httpprotocol "github.com/cloudevents/sdk-go/v2/protocol/http"
2425)
2526
27+ const UnableGetContextMsg = "unable to get keptn context from parent event %s"
28+ const UnableGetTypeMsg = "unable to get keptn event type from parent event %s"
29+
30+ const (
31+ shkeptnspecversion = "0.2.4"
32+ cloudeventsversion = "1.0"
33+ )
34+
2635const MAX_SEND_RETRIES = 3
2736
2837const DefaultHTTPEventEndpoint = "http://localhost:8081/event"
@@ -473,3 +482,169 @@ func ToKeptnEvent(event cloudevents.Event) (models.KeptnContextExtendedCE, error
473482
474483 return keptnEvent , nil
475484}
485+
486+ // CreateStartedEvent takes a parent event (e.g. .triggered event) and creates a corresponding .started event
487+ func CreateStartedEvent (source string , parentEvent models.KeptnContextExtendedCE , eventData interface {}) (* models.KeptnContextExtendedCE , error ) {
488+ if err := validateParentEvent (parentEvent ); err != nil {
489+ return nil , err
490+ }
491+
492+ startedEventType , err := ReplaceEventTypeKind (* parentEvent .Type , "started" )
493+ if err != nil {
494+ return nil , fmt .Errorf ("unable to create '.started' event for parent event %s: %w" , parentEvent .ID , err )
495+ }
496+
497+ if eventData == nil {
498+ commonEventData := EventData {}
499+ if err := parentEvent .DataAs (& commonEventData ); err != nil {
500+ logrus .Errorf ("unable to retrieve event data from parent event %s: %s" , parentEvent .ID , err .Error ())
501+ }
502+ eventData = commonEventData
503+ }
504+
505+ return createEvent (source , startedEventType , parentEvent , eventData ), nil
506+ }
507+
508+ // CreateFinishedEvent takes a parent event (e.g. .triggered event) and creates a corresponding .finished event
509+ func CreateFinishedEvent (source string , parentEvent models.KeptnContextExtendedCE , eventData interface {}) (* models.KeptnContextExtendedCE , error ) {
510+ if err := validateParentEvent (parentEvent ); err != nil {
511+ return nil , err
512+ }
513+
514+ finishedEventType , err := ReplaceEventTypeKind (* parentEvent .Type , "finished" )
515+ if err != nil {
516+ return nil , fmt .Errorf ("unable to create '.finished' event: %v from %s" , err , * parentEvent .Type )
517+ }
518+
519+ var genericEventData map [string ]interface {}
520+ err = Decode (eventData , & genericEventData )
521+ if err != nil || genericEventData == nil {
522+ return nil , fmt .Errorf ("unable to decode generic event data" )
523+ }
524+
525+ if genericEventData ["status" ] == nil || genericEventData ["status" ] == "" {
526+ genericEventData ["status" ] = "succeeded"
527+ }
528+
529+ if genericEventData ["result" ] == nil || genericEventData ["result" ] == "" {
530+ genericEventData ["result" ] = "pass"
531+ }
532+
533+ return createEvent (source , finishedEventType , parentEvent , genericEventData ), nil
534+ }
535+
536+ // CreateFinishedEventWithError takes a parent event (e.g. .triggered event) and creates a corresponding errored .finished event
537+ func CreateFinishedEventWithError (source string , parentEvent models.KeptnContextExtendedCE , eventData interface {}, errVal * Error ) (* models.KeptnContextExtendedCE , error ) {
538+ if err := validateParentEvent (parentEvent ); err != nil {
539+ return nil , err
540+ }
541+
542+ finishedEventType , err := ReplaceEventTypeKind (* parentEvent .Type , "finished" )
543+ if err != nil {
544+ return nil , fmt .Errorf ("unable to create '.finished' event for parent event %s: %w" , parentEvent .ID , err )
545+ }
546+
547+ if errVal == nil {
548+ errVal = & Error {}
549+ }
550+
551+ if eventData == nil {
552+ commonEventData := EventData {}
553+ if err := parentEvent .DataAs (& commonEventData ); err != nil {
554+ logrus .Errorf ("Unable to retrieve event data from parent event %s: %s" , parentEvent .ID , err .Error ())
555+ }
556+ commonEventData .Result = errVal .ResultType
557+ commonEventData .Status = errVal .StatusType
558+ commonEventData .Message = errVal .Message
559+ eventData = commonEventData
560+ }
561+
562+ return createEvent (source , finishedEventType , parentEvent , eventData ), nil
563+ }
564+
565+ // CreateErrorEvent takes a parent event (e.g. .triggered event) and creates a corresponding errored event
566+ func CreateErrorEvent (source string , parentEvent models.KeptnContextExtendedCE , eventData interface {}, errVal * Error ) (* models.KeptnContextExtendedCE , error ) {
567+ if err := validateParentEvent (parentEvent ); err != nil {
568+ return nil , err
569+ }
570+
571+ if errVal == nil {
572+ errVal = & Error {}
573+ }
574+
575+ if IsTaskEventType (* parentEvent .Type ) && IsTriggeredEventType (* parentEvent .Type ) {
576+ errorFinishedEvent , err := CreateFinishedEventWithError (source , parentEvent , eventData , errVal )
577+ if err != nil {
578+ return nil , err
579+ }
580+ return errorFinishedEvent , nil
581+ }
582+ errorLogEvent , err := CreateErrorLogEvent (source , parentEvent , eventData , errVal )
583+ if err != nil {
584+ return nil , err
585+ }
586+ return errorLogEvent , nil
587+ }
588+
589+ // CreateErrorLogEvent takes a parent event (e.g. .triggered event) and creates a corresponding errored .log event
590+ func CreateErrorLogEvent (source string , parentEvent models.KeptnContextExtendedCE , eventData interface {}, errVal * Error ) (* models.KeptnContextExtendedCE , error ) {
591+ if err := validateParentEvent (parentEvent ); err != nil {
592+ return nil , err
593+ }
594+
595+ if errVal == nil {
596+ errVal = & Error {}
597+ }
598+
599+ if IsTaskEventType (* parentEvent .Type ) && IsTriggeredEventType (* parentEvent .Type ) {
600+ errorFinishedEvent , err := CreateFinishedEventWithError (source , parentEvent , eventData , errVal )
601+ if err != nil {
602+ return nil , err
603+ }
604+ return errorFinishedEvent , nil
605+ }
606+
607+ if eventData == nil {
608+ errorEventData := ErrorLogEvent {}
609+ if err := parentEvent .DataAs (& errorEventData ); err != nil {
610+ logrus .Errorf ("unable to retrieve error log data from parent event %s: %s" , parentEvent .ID , err .Error ())
611+ }
612+ if IsTaskEventType (* parentEvent .Type ) {
613+ taskName , _ , err := ParseTaskEventType (* parentEvent .Type )
614+ if err == nil && taskName != "" {
615+ errorEventData .Task = taskName
616+ }
617+ }
618+ errorEventData .Message = errVal .Message
619+ eventData = errorEventData
620+ }
621+
622+ return createEvent (source , ErrorLogEventName , parentEvent , eventData ), nil
623+ }
624+
625+ func createEvent (source string , eventType string , parentEvent models.KeptnContextExtendedCE , eventData interface {}) * models.KeptnContextExtendedCE {
626+ return & models.KeptnContextExtendedCE {
627+ ID : uuid .NewString (),
628+ Triggeredid : parentEvent .ID ,
629+ Shkeptncontext : parentEvent .Shkeptncontext ,
630+ Contenttype : cloudevents .ApplicationJSON ,
631+ Data : eventData ,
632+ Source : strutils .Stringp (source ),
633+ Shkeptnspecversion : shkeptnspecversion ,
634+ Specversion : cloudeventsversion ,
635+ Time : time .Now ().UTC (),
636+ Type : strutils .Stringp (eventType ),
637+ }
638+ }
639+
640+ func validateParentEvent (parentEvent models.KeptnContextExtendedCE ) error {
641+ if parentEvent .Type == nil || * parentEvent .Type == "" {
642+ return fmt .Errorf (UnableGetTypeMsg , parentEvent .ID )
643+ }
644+
645+ if parentEvent .Shkeptncontext == "" {
646+ return fmt .Errorf (UnableGetContextMsg , parentEvent .ID )
647+ }
648+
649+ return nil
650+ }
0 commit comments