diff --git a/README.md b/README.md index add7601..a01d6b7 100644 --- a/README.md +++ b/README.md @@ -90,9 +90,10 @@ When writing code, it is recommended to follow the coding style suggested by the If you don't care about the details, your first entrypoint is [eventhandlers.go](eventhandlers.go). Within this file you can add implementation for pre-defined Keptn Cloud events. -To better understand Keptn CloudEvents, please look at the [Keptn Spec](https://github.com/keptn/spec). +To better understand all variants of Keptn CloudEvents, please look at the [Keptn Spec](https://github.com/keptn/spec). -If you want to get more insights, please look into [main.go](main.go), [deploy/service.yaml](deploy/service.yaml), +If you want to get more insights into processing those CloudEvents or even defining your own CloudEvents in code, please + look into [main.go](main.go) (specifically `processKeptnCloudEvent`), [deploy/service.yaml](deploy/service.yaml), consult the [Keptn docs](https://keptn.sh/docs/) as well as existing [Keptn Core](https://github.com/keptn/keptn) and [Keptn Contrib](https://github.com/keptn-contrib/) services. diff --git a/deploy/service.yaml b/deploy/service.yaml index f72e12a..70348d1 100644 --- a/deploy/service.yaml +++ b/deploy/service.yaml @@ -21,8 +21,6 @@ spec: ports: - containerPort: 8080 env: - - name: EVENTBROKER - value: 'http://event-broker/keptn' - name: CONFIGURATION_SERVICE value: 'http://configuration-service:8080' - name: distributor diff --git a/eventhandler_test.go b/eventhandler_test.go index f631ebe..8d1c6ca 100644 --- a/eventhandler_test.go +++ b/eventhandler_test.go @@ -9,7 +9,7 @@ import ( keptnlib "github.com/keptn/go-utils/pkg/lib" keptn "github.com/keptn/go-utils/pkg/lib/keptn" - "github.com/cloudevents/sdk-go/pkg/cloudevents" + cloudevents "github.com/cloudevents/sdk-go/v2" // make sure to use v2 cloudevents here ) /** diff --git a/eventhandlers.go b/eventhandlers.go index aca8667..f2c62b5 100644 --- a/eventhandlers.go +++ b/eventhandlers.go @@ -1,148 +1,193 @@ package main import ( + "fmt" "log" + "time" - "github.com/cloudevents/sdk-go/pkg/cloudevents" + cloudevents "github.com/cloudevents/sdk-go/v2" // make sure to use v2 cloudevents here keptn "github.com/keptn/go-utils/pkg/lib" + keptnv2 "github.com/keptn/go-utils/pkg/lib/v0_2_0" ) /** * Here are all the handler functions for the individual event - See https://github.com/keptn/spec/blob/0.1.3/cloudevents.md for details on the payload - - -> "sh.keptn.event.configuration.change" - -> "sh.keptn.events.deployment-finished" - -> "sh.keptn.events.tests-finished" - -> "sh.keptn.event.start-evaluation" - -> "sh.keptn.events.evaluation-done" - -> "sh.keptn.event.problem.open" - -> "sh.keptn.events.problem" - -> "sh.keptn.event.action.triggered" -*/ - -// Handles ConfigureMonitoringEventType = "sh.keptn.event.monitoring.configure" -func HandleConfigureMonitoringEvent(myKeptn *keptn.Keptn, incomingEvent cloudevents.Event, data *keptn.ConfigureMonitoringEventData) error { - log.Printf("Handling Configure Monitoring Event: %s", incomingEvent.Context.GetID()) +* See https://github.com/keptn/spec/blob/0.8.0-alpha/cloudevents.md for details on the payload +**/ + +// GenericLogKeptnCloudEventHandler is a generic handler for Keptn Cloud Events that logs the CloudEvent +func GenericLogKeptnCloudEventHandler(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data interface{}) error { + log.Printf("Handling %s Event: %s", incomingEvent.Type(), incomingEvent.Context.GetID()) + log.Printf("CloudEvent %T: %v", data, data) return nil } -// -// Handles ConfigurationChangeEventType = "sh.keptn.event.configuration.change" +// OldHandleConfigureMonitoringTriggeredEvent handles old configure-monitoring events // TODO: add in your handler code -// -func HandleConfigurationChangeEvent(myKeptn *keptn.Keptn, incomingEvent cloudevents.Event, data *keptn.ConfigurationChangeEventData) error { - log.Printf("Handling Configuration Changed Event: %s", incomingEvent.Context.GetID()) +func OldHandleConfigureMonitoringTriggeredEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data *keptn.ConfigureMonitoringEventData) error { + log.Printf("Handling old configure-monitoring Event: %s", incomingEvent.Context.GetID()) return nil } -// -// Handles DeploymentFinishedEventType = "sh.keptn.events.deployment-finished" +// HandleConfigureMonitoringTriggeredEvent handles configure-monitoring.triggered events // TODO: add in your handler code -// -func HandleDeploymentFinishedEvent(myKeptn *keptn.Keptn, incomingEvent cloudevents.Event, data *keptn.DeploymentFinishedEventData) error { - log.Printf("Handling Deployment Finished Event: %s", incomingEvent.Context.GetID()) - - // capture start time for tests - // startTime := time.Now() +func HandleConfigureMonitoringTriggeredEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data *keptnv2.ConfigureMonitoringTriggeredEventData) error { + log.Printf("Handling configure-monitoring.triggered Event: %s", incomingEvent.Context.GetID()) - // run tests - // ToDo: Implement your tests here - - // Send Test Finished Event - // return myKeptn.SendTestsFinishedEvent(&incomingEvent, "", "", startTime, "pass", nil, "keptn-service-template-go") return nil } -// -// Handles TestsFinishedEventType = "sh.keptn.events.tests-finished" +// HandleDeploymentTriggeredEvent handles deployment.triggered events // TODO: add in your handler code -// -func HandleTestsFinishedEvent(myKeptn *keptn.Keptn, incomingEvent cloudevents.Event, data *keptn.TestsFinishedEventData) error { - log.Printf("Handling Tests Finished Event: %s", incomingEvent.Context.GetID()) +func HandleDeploymentTriggeredEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data *keptnv2.DeploymentTriggeredEventData) error { + log.Printf("Handling deployment.triggered Event: %s", incomingEvent.Context.GetID()) return nil } -// -// Handles EvaluationDoneEventType = "sh.keptn.events.evaluation-done" +// HandleTestTriggeredEvent handles test.triggered events // TODO: add in your handler code -// -func HandleStartEvaluationEvent(myKeptn *keptn.Keptn, incomingEvent cloudevents.Event, data *keptn.StartEvaluationEventData) error { - log.Printf("Handling Start Evaluation Event: %s", incomingEvent.Context.GetID()) +func HandleTestTriggeredEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data *keptnv2.TestTriggeredEventData) error { + log.Printf("Handling test.triggered Event: %s", incomingEvent.Context.GetID()) return nil } -// -// Handles DeploymentFinishedEventType = "sh.keptn.events.deployment-finished" +// HandleEvaluationTriggeredEvent handles evaluation.triggered events // TODO: add in your handler code -// -func HandleEvaluationDoneEvent(myKeptn *keptn.Keptn, incomingEvent cloudevents.Event, data *keptn.EvaluationDoneEventData) error { - log.Printf("Handling Evaluation Done Event: %s", incomingEvent.Context.GetID()) +func HandleEvaluationTriggeredEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data *keptnv2.EvaluationTriggeredEventData) error { + log.Printf("Handling evaluation.triggered Event: %s", incomingEvent.Context.GetID()) return nil } -// -// Handles InternalGetSLIEventType = "sh.keptn.internal.event.get-sli" -// TODO: add in your handler code -// -func HandleInternalGetSLIEvent(myKeptn *keptn.Keptn, incomingEvent cloudevents.Event, data *keptn.InternalGetSLIEventData) error { - log.Printf("Handling Internal Get SLI Event: %s", incomingEvent.Context.GetID()) +// sendGetSliFinishedCloudEvent is a helper function to send a get-sli.finished event +func sendGetSliFinishedCloudEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data *keptnv2.GetSLITriggeredEventData, + status keptnv2.StatusType, result keptnv2.ResultType, message string) error { + log.Printf("Sending getSli Finished Cloud Event with status=%s and result=%s back to Keptn (%s)", status, result, message) + getSliFinishedEventData := keptnv2.GetSLIFinishedEventData{} + + getSliFinishedEventData.EventData = data.EventData + getSliFinishedEventData.Status = status + getSliFinishedEventData.Result = result + getSliFinishedEventData.Message = message + + // Convert To CloudEvent + finishedEvent := cloudevents.NewEvent() + finishedEvent.SetType(keptnv2.GetFinishedEventType(keptnv2.GetSLITaskName)) + finishedEvent.SetData(cloudevents.ApplicationJSON, getSliFinishedEventData) + + return SendEvent(myKeptn, finishedEvent, incomingEvent) +} - incomingGetSLIEventData := &keptn.InternalGetSLIEventData{} - incomingEvent.DataAs(incomingGetSLIEventData) +// HandleGetSliEvent handles get-sli events +// TODO: adapt handler code to your needs +func HandleGetSliEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data *keptnv2.GetSLITriggeredEventData) error { + log.Printf("Handling get-sli.triggered Event: %s", incomingEvent.Context.GetID()) // Step 1 - Do we need to do something? // Lets make sure we are only processing an event that really belongs to our SLI Provider - /* if incomingGetSLIEventData.SLIProvider != "keptn-service-template-go" { + if data.GetSLI.SLIProvider != "keptn-service-template-go" { + log.Printf("Not handling get-sli event as it is meant for %s", data.GetSLI.SLIProvider) return nil - }*/ + } + + // Step 2 - Send out a get-sli.started CloudEvent + // The get-sli.started cloud-event is new since Keptn 0.8.0 and is required for the task to start + getSliStartedData := keptnv2.GetSLIStartedEventData{} + + getSliStartedData.EventData = data.EventData + getSliStartedData.Status = keptnv2.StatusSucceeded // alternative: keptnv2.StatusErrored + getSliStartedData.Result = keptnv2.ResultPass // alternative: keptnv2.ResultFailed - // Step 2 - prep-work - // Get any additional input / configuration data, e.g - // Labels: get the incoming labels for potential config data and use it to pass more labels on result, e.g: links - // SLI.yaml: if your service uses SLI.yaml to store query definitions for SLIs get that file from Keptn - /* labels := incomingGetSLIEventData.Labels + // Convert To CloudEvent + startedEvent := cloudevents.NewEvent() + startedEvent.SetType(keptnv2.GetStartedEventType(keptnv2.GetSLITaskName)) + startedEvent.SetData(cloudevents.ApplicationJSON, getSliStartedData) + + // send action.started event + SendEvent(myKeptn, startedEvent, incomingEvent) + + // Step 4 - prep-work + // Get any additional input / configuration data + // - Labels: get the incoming labels for potential config data and use it to pass more labels on result, e.g: links + // - SLI.yaml: if your service uses SLI.yaml to store query definitions for SLIs get that file from Keptn + labels := data.Labels if labels == nil { labels = make(map[string]string) } - testRunID := labels["testRunId"]*/ + testRunID := labels["testRunId"] + + // Step 5 - get SLI Config File + // Get SLI File from keptn-service-template-go subdirectory of the config repo - to add the file use: + // keptn add-resource --project=PROJECT --stage=STAGE --service=SERVICE --resource=my-sli-config.yaml --resourceUri=keptn-service-template-go/sli.yaml + sliFile := "keptn-service-template-go/sli.yaml" + sliConfigFileContent, err := myKeptn.GetKeptnResource(sliFile) + + if err != nil { + // failed to fetch sli config file + errMsg := fmt.Sprintf("Failed to fetch SLI file %s from config repo: %s", sliFile, err.Error()) + log.Println(errMsg) + // send a get-sli.finished event with status=error and result=failed back to Keptn + return sendGetSliFinishedCloudEvent(myKeptn, incomingEvent, data, keptnv2.StatusErrored, keptnv2.ResultFailed, errMsg) + } - // sliConfigFileContent, err := myKeptn.GetKeptnResource("keptn-service-template-go/sli.yaml") + fmt.Println(sliConfigFileContent) - // Step 3 - do your work - iterate through the list of requested indicators and return their values + // Step 6 - do your work - iterate through the list of requested indicators and return their values // Indicators: this is the list of indicators as requested in the SLO.yaml // SLIResult: this is the array that will receive the results - /* indicators := incomingGetSLIEventData.Indicators - sliResults := []*keptn.SLIResult{} + indicators := data.GetSLI.Indicators + sliResults := []*keptnv2.SLIResult{} for _, indicatorName := range indicators { - sliResult := &keptn.SLIResult{ + sliResult := &keptnv2.SLIResult{ Metric: indicatorName, - Value: 123.4, + Value: 123.4, // ToDo: Fetch the values from your monitoring tool here } sliResults = append(sliResults, sliResult) - }*/ + } - // Step 4 - add additional context via labels - // labels["Link to Data Source"] = "https://mydatasource/myquery?testRun=" + testRunID + // Step 7 - add additional context via labels (e.g., a backlink to the monitoring or CI tool) + labels["Link to Data Source"] = "https://mydatasource/myquery?testRun=" + testRunID + + // Step 8 - Build get-sli.finished event data + getSliFinishedEventData := keptnv2.GetSLIFinishedEventData{ + EventData: keptnv2.EventData{ + Project: data.Project, + Stage: data.Stage, + Service: data.Service, + Labels: labels, + Status: keptnv2.StatusSucceeded, + Result: keptnv2.ResultPass, + }, + GetSLI: struct { + Start string `json:"start"` + End string `json:"end"` + IndicatorValues []*keptnv2.SLIResult `json:"indicatorValues"` + }{ + IndicatorValues: sliResults, + Start: data.GetSLI.Start, + End: data.GetSLI.End, + }, + } - // Step 4 - send results back to Keptn - // return myKeptn.SendInternalGetSLIDoneEvent(incomingGetSLIEventData, sliResults, labels, err, "keptn-service-template-go") + // Step 8 - Convert To CloudEvent + finishedEvent := cloudevents.NewEvent() + finishedEvent.SetType(keptnv2.GetFinishedEventType(keptnv2.GetSLITaskName)) + finishedEvent.SetData(cloudevents.ApplicationJSON, getSliFinishedEventData) - return nil + // Step 9 - send action.finished CloudEvent back to Keptn + return SendEvent(myKeptn, finishedEvent, incomingEvent) } -// -// Handles ProblemOpenEventType = "sh.keptn.event.problem.open" -// Handles ProblemEventType = "sh.keptn.events.problem" +// HandleProblemEvent handles two problem events: +// - ProblemOpenEventType = "sh.keptn.event.problem.open" +// - ProblemEventType = "sh.keptn.events.problem" // TODO: add in your handler code -// -func HandleProblemEvent(myKeptn *keptn.Keptn, incomingEvent cloudevents.Event, data *keptn.ProblemEventData) error { +func HandleProblemEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data *keptn.ProblemEventData) error { log.Printf("Handling Problem Event: %s", incomingEvent.Context.GetID()) // Deprecated since Keptn 0.7.0 - use the HandleActionTriggeredEvent instead @@ -150,20 +195,61 @@ func HandleProblemEvent(myKeptn *keptn.Keptn, incomingEvent cloudevents.Event, d return nil } -// -// Handles ActionTriggeredEventType = "sh.keptn.event.action.triggered" +// HandleActionTriggeredEvent handles action.triggered events // TODO: add in your handler code -// -func HandleActionTriggeredEvent(myKeptn *keptn.Keptn, incomingEvent cloudevents.Event, data *keptn.ActionTriggeredEventData) error { +func HandleActionTriggeredEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data *keptnv2.ActionTriggeredEventData) error { log.Printf("Handling Action Triggered Event: %s", incomingEvent.Context.GetID()) + log.Printf("Action=%s\n", data.Action.Action) // check if action is supported if data.Action.Action == "action-xyz" { - //myKeptn.SendActionStartedEvent() + // ----------------------------------------------------- + // 1. Send Action.Started Cloud-Event + // ----------------------------------------------------- + + // generate an action.started event + actionStartedData := keptnv2.ActionStartedEventData{} + + actionStartedData.EventData = data.EventData + actionStartedData.Status = keptnv2.StatusSucceeded // alternative: keptnv2.StatusErrored + actionStartedData.Result = keptnv2.ResultPass // alternative: keptnv2.ResultFailed + + // Convert To CloudEvent + startedEvent := cloudevents.NewEvent() + startedEvent.SetType(keptnv2.GetStartedEventType(keptnv2.ActionTaskName)) + startedEvent.SetData(cloudevents.ApplicationJSON, actionStartedData) + + // send action.started event + SendEvent(myKeptn, startedEvent, incomingEvent) - // Implement your remediation action here + // ----------------------------------------------------- + // 2. Implement your remediation action here + // ----------------------------------------------------- + time.Sleep(5 * time.Second) // Example: Wait 5 seconds. Maybe the problem fixes itself. - //myKeptn.SendActionFinishedEvent() + // ----------------------------------------------------- + // 3. Send Action.Finished Cloud-Event + // ----------------------------------------------------- + + // generate an action.finished event + actionFinishedData := keptnv2.ActionFinishedEventData{} + + actionFinishedData.EventData = data.EventData + actionFinishedData.Status = keptnv2.StatusSucceeded // alternative: keptnv2.StatusErrored + actionFinishedData.Result = keptnv2.ResultPass // alternative: keptnv2.ResultFailed + actionFinishedData.Message = "Successfully sleeped!" + + // Convert To CloudEvent + finishedEvent := cloudevents.NewEvent() + finishedEvent.SetType(keptnv2.GetFinishedEventType(keptnv2.ActionTaskName)) + finishedEvent.SetData(cloudevents.ApplicationJSON, actionFinishedData) + + // send action.finished event + SendEvent(myKeptn, finishedEvent, incomingEvent) + + } else { + log.Printf("Retrieved unknown action %s, skipping...", data.Action.Action) + return nil } return nil } diff --git a/go.mod b/go.mod index 61d33f3..140b2c2 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,11 @@ module example.com/keptn-service-template-go go 1.13 require ( - github.com/cloudevents/sdk-go v1.1.2 + github.com/cloudevents/sdk-go v1.1.2 // indirect + github.com/cloudevents/sdk-go/v2 v2.2.0 + github.com/google/uuid v1.1.1 github.com/kelseyhightower/envconfig v1.4.0 - github.com/keptn/go-utils v0.8.0-alpha + github.com/keptn/go-utils v0.8.0-alpha.0.20210113154602-3a846009dff4 github.com/onsi/ginkgo v1.12.0 // indirect github.com/onsi/gomega v1.9.0 // indirect ) diff --git a/go.sum b/go.sum index d4380fd..bb3c6b8 100644 --- a/go.sum +++ b/go.sum @@ -34,6 +34,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cloudevents/sdk-go v0.10.0/go.mod h1:PW8UwWI6tD2Ry5kFpZfV1qlrADFkfaDCZXLiJ1dC1Ks= github.com/cloudevents/sdk-go v1.1.2 h1:mg/7d+BzubBPrPpH1bdeF85BQZYV85j7Ljqat3+m+qE= github.com/cloudevents/sdk-go v1.1.2/go.mod h1:ss+jWJ88wypiewnPEzChSBzTYXGpdcILoN9YHk8uhTQ= +github.com/cloudevents/sdk-go/v2 v2.2.0 h1:FlBJg7W0QywbOjuZGmRXUyFk8qkCHx2euETp+tuopSU= github.com/cloudevents/sdk-go/v2 v2.2.0/go.mod h1:3CTrpB4+u7Iaj6fd7E2Xvm5IxMdRoaAhqaRVnOr2rCU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -143,8 +144,11 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= +github.com/keptn/go-utils v0.7.1 h1:qDViu8qhijdh7QK1+k+i4hEDtTwkHo2PxsomxKvxlpg= github.com/keptn/go-utils v0.8.0-alpha h1:h+yUaI8pmM3VqxRgBQAENrFZ7GafyIWMOPfwHkohkAk= github.com/keptn/go-utils v0.8.0-alpha/go.mod h1:SmTTNxBonQXC4/nxkqAWtVm4WjqEfu8r7EPQe8LZ1/Y= +github.com/keptn/go-utils v0.8.0-alpha.0.20210113154602-3a846009dff4 h1:qmkDojXAdmFSzhY6oFHktitEIbVQvBcZDMXLmcQfO1E= +github.com/keptn/go-utils v0.8.0-alpha.0.20210113154602-3a846009dff4/go.mod h1:SmTTNxBonQXC4/nxkqAWtVm4WjqEfu8r7EPQe8LZ1/Y= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -228,6 +232,7 @@ github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1 h1:Sq1fR+0c58RME5EoqKdjkiQAmPjmfHlZOoRI6fTUOcs= diff --git a/main.go b/main.go index 9b92c38..0fe18d0 100644 --- a/main.go +++ b/main.go @@ -7,13 +7,12 @@ import ( "log" "os" + cloudevents "github.com/cloudevents/sdk-go/v2" // make sure to use v2 cloudevents here + "github.com/google/uuid" + "github.com/kelseyhightower/envconfig" keptnlib "github.com/keptn/go-utils/pkg/lib" keptn "github.com/keptn/go-utils/pkg/lib/keptn" - - "github.com/cloudevents/sdk-go/pkg/cloudevents" - "github.com/cloudevents/sdk-go/pkg/cloudevents/client" - cloudeventshttp "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http" - "github.com/kelseyhightower/envconfig" + keptnv2 "github.com/keptn/go-utils/pkg/lib/v0_2_0" ) var keptnOptions = keptn.KeptnOpts{} @@ -27,17 +26,71 @@ type envConfig struct { Env string `envconfig:"ENV" default:"local"` // URL of the Keptn configuration service (this is where we can fetch files from the config repo) ConfigurationServiceUrl string `envconfig:"CONFIGURATION_SERVICE" default:""` - // URL of the Keptn event broker (this is where this service sends cloudevents to) - EventBrokerUrl string `envconfig:"EVENTBROKER" default:""` +} + +// ServiceName specifies the current services name (e.g., used as source when sending CloudEvents) +const ServiceName = "keptn-service-template-go" + +// SendEvent sends a cloud event +func SendEvent(myKeptn *keptnv2.Keptn, event cloudevents.Event, incomingEvent cloudevents.Event) error { + log.Printf("Sending CloudEvent back to Keptn: %s %s", event.Type(), event.Context.GetID()) + // set source of CloudEvent + event.SetSource(ServiceName) + event.SetDataContentType(cloudevents.ApplicationJSON) + + event.SetID(uuid.New().String()) + + // set keptn context + event.SetExtension("shkeptncontext", myKeptn.KeptnContext) + + // set triggered id to event id of incoming event + event.SetExtension("triggeredid", incomingEvent.Context.GetID()) + + err := event.Validate() + + if err != nil { + log.Printf("CloudEvent Validation Failed: %s", err) + return err + } + + // Print CE + log.Printf("%v", event) + + err = myKeptn.SendCloudEvent(event) + + if err != nil { + log.Fatalf("Failed to send CloudEvent: %s", err.Error()) + return err + } + + log.Printf("Keptn CloudEvent sent!") + + return nil +} + +/** + * Parses a Keptn Cloud Event payload (data attribute) + */ +func parseKeptnCloudEventPayload(event cloudevents.Event, data interface{}) error { + err := event.DataAs(data) + if err != nil { + log.Fatalf("Got Data Error: %s", err.Error()) + return err + } + return nil } /** * This method gets called when a new event is received from the Keptn Event Distributor * Depending on the Event Type will call the specific event handler functions, e.g: handleDeploymentFinishedEvent - * See https://github.com/keptn/spec/blob/0.1.3/cloudevents.md for details on the payload + * See https://github.com/keptn/spec/blob/0.2.0-alpha/cloudevents.md for details on the payload */ func processKeptnCloudEvent(ctx context.Context, event cloudevents.Event) error { - myKeptn, err := keptnlib.NewKeptn(&event, keptnOptions) + // create keptn handler + myKeptn, err := keptnv2.NewKeptn(&event, keptnOptions) + if err != nil { + return errors.New("Could not create Keptn Handler: " + err.Error()) + } log.Printf("gotEvent(%s): %s - %s", event.Type(), myKeptn.KeptnContext, event.Context.GetID()) @@ -46,99 +99,476 @@ func processKeptnCloudEvent(ctx context.Context, event cloudevents.Event) error return err } - // ******************************************** - // Lets test on each possible Event Type and call the respective handler function - // ******************************************** - if event.Type() == keptnlib.ConfigurationChangeEventType { - log.Printf("Processing Configuration Change Event") - - configChangeEventData := &keptnlib.ConfigurationChangeEventData{} - err := event.DataAs(configChangeEventData) - if err != nil { - log.Printf("Got Data Error: %s", err.Error()) - return err - } - - return HandleConfigurationChangeEvent(myKeptn, event, configChangeEventData) - } else if event.Type() == keptnlib.DeploymentFinishedEventType { - log.Printf("Processing Deployment Finished Event") - - deployFinishEventData := &keptnlib.DeploymentFinishedEventData{} - err := event.DataAs(deployFinishEventData) - if err != nil { - log.Printf("Got Data Error: %s", err.Error()) - return err - } - - return HandleDeploymentFinishedEvent(myKeptn, event, deployFinishEventData) - } else if event.Type() == keptnlib.TestsFinishedEventType { - log.Printf("Processing Test Finished Event") - - testsFinishedEventData := &keptnlib.TestsFinishedEventData{} - err := event.DataAs(testsFinishedEventData) - if err != nil { - log.Printf("Got Data Error: %s", err.Error()) - return err - } - - return HandleTestsFinishedEvent(myKeptn, event, testsFinishedEventData) - } else if event.Type() == keptnlib.StartEvaluationEventType { - log.Printf("Processing Start Evaluation Event") - - startEvaluationEventData := &keptnlib.StartEvaluationEventData{} - err := event.DataAs(startEvaluationEventData) - if err != nil { - log.Printf("Got Data Error: %s", err.Error()) - return err - } - - return HandleStartEvaluationEvent(myKeptn, event, startEvaluationEventData) - } else if event.Type() == keptnlib.EvaluationDoneEventType { - log.Printf("Processing Evaluation Done Event") - - evaluationDoneEventData := &keptnlib.EvaluationDoneEventData{} - err := event.DataAs(evaluationDoneEventData) - if err != nil { - log.Printf("Got Data Error: %s", err.Error()) - return err - } - - return HandleEvaluationDoneEvent(myKeptn, event, evaluationDoneEventData) - } else if event.Type() == keptnlib.ProblemOpenEventType || event.Type() == keptnlib.ProblemEventType { - // Subscribing to a problem.open or problem event is deprecated since Keptn 0.7 - subscribe to sh.keptn.event.action.triggered + /** + * CloudEvents types in Keptn 0.8.0 follow the following pattern: + * - sh.keptn.event.${EVENTNAME}.triggered + * - sh.keptn.event.${EVENTNAME}.started + * - sh.keptn.event.${EVENTNAME}.status.changed + * - sh.keptn.event.${EVENTNAME}.finished + * + * For convenience, types can be generated using the following methods: + * - triggered: keptnv2.GetTriggeredEventType(${EVENTNAME}) (e.g,. keptnv2.GetTriggeredEventType(keptnv2.DeploymentTaskName)) + * - started: keptnv2.GetStartedEventType(${EVENTNAME}) (e.g,. keptnv2.GetStartedEventType(keptnv2.DeploymentTaskName)) + * - status.changed: keptnv2.GetStatusChangedEventType(${EVENTNAME}) (e.g,. keptnv2.GetStatusChangedEventType(keptnv2.DeploymentTaskName)) + * - finished: keptnv2.GetFinishedEventType(${EVENTNAME}) (e.g,. keptnv2.GetFinishedEventType(keptnv2.DeploymentTaskName)) + * + * The following Cloud Events are reserved and specified in the Keptn spec: + * - approval + * - deployment + * - test + * - evaluation + * - release + * - remediation + * - action + * - get-sli (for quality-gate SLI providers) + * - problem / problem.open (both deprecated, use action or remediation instead) + + * There are more "internal" Cloud Events that might not have all four status, e.g.: + * - project + * - project.create + * - service + * - service.create + * - configure-monitoring + * + * For those Cloud Events the keptn/go-utils library conveniently provides several data structures + * and strings in github.com/keptn/go-utils/pkg/lib/v0_2_0, e.g.: + * - deployment: DeploymentTaskName, DeploymentTriggeredEventData, DeploymentStartedEventData, DeploymentFinishedEventData + * - test: TestTaskName, TestTriggeredEventData, TestStartedEventData, TestFinishedEventData + * - ... (they all follow the same pattern) + * + * + * In most cases you will be interested in processing .triggered events (e.g., sh.keptn.event.deployment.triggered), + * which you an achieve as follows: + * if event.type() == keptnv2.GetTriggeredEventType(keptnv2.DeploymentTaskName) { ... } + * + * Processing the event payload can be achieved as follows: + * + * eventData := &keptnv2.DeploymentTriggeredEventData{} + * parseKeptnCloudEventPayload(event, eventData) + * + * See https://github.com/keptn/spec/blob/0.2.0-alpha/cloudevents.md for more details of Keptn Cloud Events and their payload + * Also, see https://github.com/keptn-sandbox/echo-service/blob/a90207bc119c0aca18368985c7bb80dea47309e9/pkg/events.go as an example how to create your own CloudEvents + **/ + + /** + * The following code presents a very generic implementation of processing almost all possible + * Cloud Events that are retrieved by this service. + * Please follow the documentation provided above for more guidance on the different types. + * Feel free to delete parts that you don't need. + **/ + switch event.Type() { + + // ------------------------------------------------------- + // sh.keptn.event.project.create - Note: This is due to change + case keptnv2.GetStartedEventType(keptnv2.ProjectCreateTaskName): // sh.keptn.event.project.create.started + log.Printf("Processing Project.Create.Started Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + eventData := &keptnv2.ProjectCreateStartedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + case keptnv2.GetFinishedEventType(keptnv2.ProjectCreateTaskName): // sh.keptn.event.project.create.finished + log.Printf("Processing Project.Create.Finished Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + eventData := &keptnv2.ProjectCreateFinishedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Post-handler for deployment.finished Cloud Events (e.g., modify helm-chart, ...) + + break + + // ------------------------------------------------------- + // sh.keptn.event.service.create - Note: This is due to change + case keptnv2.GetStartedEventType(keptnv2.ServiceCreateTaskName): // sh.keptn.event.service.create.started + log.Printf("Processing Service.Create.Started Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + eventData := &keptnv2.ServiceCreateStartedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + case keptnv2.GetFinishedEventType(keptnv2.ServiceCreateTaskName): // sh.keptn.event.service.create.finished + log.Printf("Processing Service.Create.Finished Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + eventData := &keptnv2.ServiceCreateFinishedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Post-handler for deployment.finished Cloud Events (e.g., modify helm-chart, ...) + + break + + // ------------------------------------------------------- + // sh.keptn.event.approval + case keptnv2.GetTriggeredEventType(keptnv2.ApprovalTaskName): // sh.keptn.event.approval.triggered + log.Printf("Processing Approval.Triggered Event") + + eventData := &keptnv2.ApprovalTriggeredEventData{} + parseKeptnCloudEventPayload(event, eventData) + + break + case keptnv2.GetStartedEventType(keptnv2.ApprovalTaskName): // sh.keptn.event.approval.started + log.Printf("Processing Approval.Started Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + eventData := &keptnv2.ApprovalStartedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + case keptnv2.GetFinishedEventType(keptnv2.ApprovalTaskName): // sh.keptn.event.approval.finished + log.Printf("Processing Approval.Finished Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + eventData := &keptnv2.ApprovalFinishedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + + // ------------------------------------------------------- + // sh.keptn.event.deployment + case keptnv2.GetTriggeredEventType(keptnv2.DeploymentTaskName): // sh.keptn.event.deployment.triggered + log.Printf("Processing Deployment.Triggered Event") + + eventData := &keptnv2.DeploymentTriggeredEventData{} + parseKeptnCloudEventPayload(event, eventData) + + break + case keptnv2.GetStartedEventType(keptnv2.DeploymentTaskName): // sh.keptn.event.deployment.started + log.Printf("Processing Deployment.Started Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + eventData := &keptnv2.DeploymentStartedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + case keptnv2.GetStatusChangedEventType(keptnv2.DeploymentTaskName): // sh.keptn.event.deployment.status.changed + log.Printf("Processing Deployment.Started Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + // Todo: ? + + break + case keptnv2.GetFinishedEventType(keptnv2.DeploymentTaskName): // sh.keptn.event.deployment.finished + log.Printf("Processing Deployment.Finished Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + eventData := &keptnv2.DeploymentFinishedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + + // ------------------------------------------------------- + // sh.keptn.event.test + case keptnv2.GetTriggeredEventType(keptnv2.TestTaskName): // sh.keptn.event.test.triggered + log.Printf("Processing Test.Triggered Event") + + eventData := &keptnv2.TestTriggeredEventData{} + parseKeptnCloudEventPayload(event, eventData) + + break + case keptnv2.GetStartedEventType(keptnv2.TestTaskName): // sh.keptn.event.test.started + log.Printf("Processing Test.Started Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + eventData := &keptnv2.TestStartedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + case keptnv2.GetStatusChangedEventType(keptnv2.TestTaskName): // sh.keptn.event.test.status.changed + log.Printf("Processing Test.Started Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + // Todo ? + + break + case keptnv2.GetFinishedEventType(keptnv2.TestTaskName): // sh.keptn.event.test.finished + log.Printf("Processing Test.Finished Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + eventData := &keptnv2.TestFinishedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + + // ------------------------------------------------------- + // sh.keptn.event.evaluation + case keptnv2.GetTriggeredEventType(keptnv2.EvaluationTaskName): // sh.keptn.event.evaluation.triggered + log.Printf("Processing Evaluation.Triggered Event") + + eventData := &keptnv2.EvaluationTriggeredEventData{} + parseKeptnCloudEventPayload(event, eventData) + + break + case keptnv2.GetStartedEventType(keptnv2.EvaluationTaskName): // sh.keptn.event.evaluation.started + log.Printf("Processing Evaluation.Started Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + eventData := &keptnv2.EvaluationStartedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + case keptnv2.GetFinishedEventType(keptnv2.EvaluationTaskName): // sh.keptn.event.evaluation.finished + log.Printf("Processing Evaluation.Finished Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + eventData := &keptnv2.EvaluationFinishedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + + // ------------------------------------------------------- + // sh.keptn.event.release + case keptnv2.GetTriggeredEventType(keptnv2.ReleaseTaskName): // sh.keptn.event.release.triggered + log.Printf("Processing Release.Triggered Event") + + eventData := &keptnv2.ReleaseTriggeredEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // ToDo ? + + break + case keptnv2.GetStartedEventType(keptnv2.ReleaseTaskName): // sh.keptn.event.release.started + log.Printf("Processing Release.Started Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + eventData := &keptnv2.ReleaseStartedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + case keptnv2.GetStatusChangedEventType(keptnv2.ReleaseTaskName): // sh.keptn.event.release.status.changed + log.Printf("Processing Release.Status.Changed Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + eventData := &keptnv2.ReleaseStatusChangedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + case keptnv2.GetFinishedEventType(keptnv2.ReleaseTaskName): // sh.keptn.event.release.finished + log.Printf("Processing Release.Finished Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + eventData := &keptnv2.ReleaseFinishedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + + // ------------------------------------------------------- + // sh.keptn.event.remediation + // ToDo: Replace "remediation" with keptnv2.RemediationTaskName once this PR has been merged: https://github.com/keptn/go-utils/pull/230 + case keptnv2.GetTriggeredEventType(keptnv2.RemediationTaskName): // sh.keptn.event.remediation.triggered + log.Printf("Processing Remediation.Triggered Event") + + eventData := &keptnv2.RemediationTriggeredEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // ToDo ? + + break + case keptnv2.GetStartedEventType(keptnv2.RemediationTaskName): // sh.keptn.event.remediation.started + log.Printf("Processing Remediation.Started Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + eventData := &keptnv2.RemediationStartedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + case keptnv2.GetStatusChangedEventType(keptnv2.RemediationTaskName): // sh.keptn.event.remediation.status.changed + log.Printf("Processing Remediation.Started Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + eventData := &keptnv2.RemediationStatusChangedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + case keptnv2.GetFinishedEventType(keptnv2.RemediationTaskName): // sh.keptn.event.remediation.finished + log.Printf("Processing Remediation.Finished Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + eventData := &keptnv2.RemediationFinishedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + + // ------------------------------------------------------- + // sh.keptn.event.action + case keptnv2.GetTriggeredEventType(keptnv2.ActionTaskName): // sh.keptn.event.action.triggered + log.Printf("Processing Action.Triggered Event") + + eventData := &keptnv2.ActionTriggeredEventData{} + parseKeptnCloudEventPayload(event, eventData) + + return HandleActionTriggeredEvent(myKeptn, event, eventData) + case keptnv2.GetStartedEventType(keptnv2.ActionTaskName): // sh.keptn.event.action.started + log.Printf("Processing Action.Started Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + eventData := &keptnv2.ActionStartedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + case keptnv2.GetFinishedEventType(keptnv2.ActionTaskName): // sh.keptn.event.action.finished + log.Printf("Processing Action.Finished Event") + // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to + // notify an external service (e.g., for logging purposes). + + eventData := &keptnv2.ActionFinishedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + + // ------------------------------------------------------- + // sh.keptn.event.problem / problem.open + // Please Note: This is deprecated; Use Action.Triggered instead + case keptnlib.ProblemEventType: // sh.keptn.event.problem - e.g., sent by Dynatrace to Keptn Api + log.Printf("Processing problem Event") log.Printf("Subscribing to a problem.open or problem event is not recommended since Keptn 0.7. Please subscribe to event of type: sh.keptn.event.action.triggered") - log.Printf("Processing Problem Event") - - problemEventData := &keptnlib.ProblemEventData{} - err := event.DataAs(problemEventData) - if err != nil { - log.Printf("Got Data Error: %s", err.Error()) - return err - } - - return HandleProblemEvent(myKeptn, event, problemEventData) - } else if event.Type() == keptnlib.ActionTriggeredEventType { - log.Printf("Processing Action Triggered Event") - - actionTriggeredEventData := &keptnlib.ActionTriggeredEventData{} - err := event.DataAs(actionTriggeredEventData) - if err != nil { - log.Printf("Got Data Error: %s", err.Error()) - return err - } - - return HandleActionTriggeredEvent(myKeptn, event, actionTriggeredEventData) - } else if event.Type() == keptnlib.ConfigureMonitoringEventType { - log.Printf("Processing Configure Monitoring Event") - - configureMonitoringEventData := &keptnlib.ConfigureMonitoringEventData{} - err := event.DataAs(configureMonitoringEventData) - if err != nil { - log.Printf("Got Data Error: %s", err.Error()) - return err - } - - return HandleConfigureMonitoringEvent(myKeptn, event, configureMonitoringEventData) + + eventData := &keptnlib.ProblemEventData{} + parseKeptnCloudEventPayload(event, eventData) + + return HandleProblemEvent(myKeptn, event, eventData) + case keptnlib.ProblemOpenEventType: // sh.keptn.event.problem.open - e.g., sent by dynatrace-service + log.Printf("Processing problem.open Event") + log.Printf("Subscribing to a problem.open or problem event is not recommended since Keptn 0.7. Please subscribe to event of type: sh.keptn.event.action.triggered") + + eventData := &keptnlib.ProblemEventData{} + parseKeptnCloudEventPayload(event, eventData) + + return HandleProblemEvent(myKeptn, event, eventData) + + // ------------------------------------------------------- + // sh.keptn.event.get-sli + case keptnv2.GetTriggeredEventType(keptnv2.GetSLITaskName): // sh.keptn.event.get-sli.triggered + log.Printf("Processing Get-SLI.Triggered Event") + + eventData := &keptnv2.GetSLITriggeredEventData{} + parseKeptnCloudEventPayload(event, eventData) + + return HandleGetSliEvent(myKeptn, event, eventData) + case keptnv2.GetStartedEventType(keptnv2.GetSLITaskName): // sh.keptn.event.get-sli.started + log.Printf("Processing Get-SLI.Started Event") + + eventData := &keptnv2.GetSLIStartedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + case keptnv2.GetFinishedEventType(keptnv2.GetSLITaskName): // sh.keptn.event.get-sli.finished + log.Printf("Processing Get-SLI.Finished Event") + + eventData := &keptnv2.GetSLIFinishedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + + // ------------------------------------------------------- + // sh.keptn.event.configure-monitoring + case keptnlib.ConfigureMonitoringEventType: // old configure-monitoring CE; compatibility with 0.8.0-alpha + log.Printf("Processing old configure-monitoring Event") + log.Printf("Note: This will be deprecated with Keptn 0.8.0") + + eventData := &keptnlib.ConfigureMonitoringEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Handle old configure-monitoring event + return OldHandleConfigureMonitoringTriggeredEvent(myKeptn, event, eventData) + + case keptnv2.GetTriggeredEventType(keptnv2.ConfigureMonitoringTaskName): // sh.keptn.event.configure-monitoring.triggered + log.Printf("Processing configure-monitoring.Triggered Event") + + eventData := &keptnv2.ConfigureMonitoringTriggeredEventData{} + parseKeptnCloudEventPayload(event, eventData) + + return HandleConfigureMonitoringTriggeredEvent(myKeptn, event, eventData) + case keptnv2.GetStartedEventType(keptnv2.ConfigureMonitoringTaskName): // sh.keptn.event.configure-monitoring.started + log.Printf("Processing configure-monitoring.Started Event") + + eventData := &keptnv2.ConfigureMonitoringStartedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + case keptnv2.GetFinishedEventType(keptnv2.ConfigureMonitoringTaskName): // sh.keptn.event.configure-monitoring.finished + log.Printf("Processing configure-monitoring.Finished Event") + + eventData := &keptnv2.ConfigureMonitoringFinishedEventData{} + parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + + // ------------------------------------------------------- + // your custom cloud event, e.g., sh.keptn.your-event + // see https://github.com/keptn-sandbox/echo-service/blob/a90207bc119c0aca18368985c7bb80dea47309e9/pkg/events.go + // for an example on how to generate your own CloudEvents and structs + case keptnv2.GetTriggeredEventType("your-event"): // sh.keptn.event.your-event.triggered + log.Printf("Processing your-event.triggered Event") + + // eventData := &keptnv2.YourEventTriggeredEventData{} + // parseKeptnCloudEventPayload(event, eventData) + + break + case keptnv2.GetStartedEventType(keptnv2.ConfigureMonitoringTaskName): // sh.keptn.event.your-event.started + log.Printf("Processing your-event.started Event") + + // eventData := &keptnv2.YourEventStartedEventData{} + // parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + // return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + + break + case keptnv2.GetFinishedEventType(keptnv2.ConfigureMonitoringTaskName): // sh.keptn.event.your-event.finished + log.Printf("Processing your-event.finished Event") + + // eventData := &keptnv2.YourEventFinishedEventData{} + // parseKeptnCloudEventPayload(event, eventData) + + // Just log this event + // return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) + + break } // Unknown Event -> Throw Error! @@ -169,8 +599,6 @@ func main() { * Opens up a listener on localhost:port/path and passes incoming requets to gotEvent */ func _main(args []string, env envConfig) int { - ctx := context.Background() - // configure keptn options if env.Env == "local" { log.Println("env=local: Running with local filesystem to fetch resources") @@ -178,26 +606,23 @@ func _main(args []string, env envConfig) int { } keptnOptions.ConfigurationServiceURL = env.ConfigurationServiceUrl - keptnOptions.EventBrokerURL = env.EventBrokerUrl - - // configure http server to receive cloudevents - t, err := cloudeventshttp.New( - cloudeventshttp.WithPort(env.Port), - cloudeventshttp.WithPath(env.Path), - ) log.Println("Starting keptn-service-template-go...") log.Printf(" on Port = %d; Path=%s", env.Port, env.Path) + ctx := context.Background() + ctx = cloudevents.WithEncodingStructured(ctx) + + // configure http server to receive cloudevents + p, err := cloudevents.NewHTTP(cloudevents.WithPath(env.Path), cloudevents.WithPort(env.Port)) if err != nil { - log.Fatalf("failed to create transport, %v", err) + log.Fatalf("failed to create client, %v", err) } - c, err := client.New(t) + c, err := cloudevents.NewClient(p) if err != nil { log.Fatalf("failed to create client, %v", err) } - - log.Fatalf("failed to start receiver: %s", c.StartReceiver(ctx, processKeptnCloudEvent)) + log.Fatal(c.StartReceiver(ctx, processKeptnCloudEvent)) return 0 }