From ac06bf86cb297401236dffa11761e0fe6c3bdb66 Mon Sep 17 00:00:00 2001 From: Arthur Pitman Date: Wed, 12 Jan 2022 17:33:27 +0100 Subject: [PATCH] fix: `ProblemEventHandler` sends `sh.keptn.event.[STAGE].remediation.triggered` event even if stage is not set (#672) * fix: Drop open problem events with no stage Signed-off-by: Arthur Pitman * Force PR title as commit message Signed-off-by: Arthur Pitman --- documentation/problem-forwarding-to-keptn.md | 3 +- internal/problem/problem_event_handler.go | 5 +++ .../problem/problem_event_handler_test.go | 18 ++++++++-- .../open_problem_no_stage/received_ce.json | 36 +++++++++++++++++++ 4 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 internal/problem/testdata/open_problem_no_stage/received_ce.json diff --git a/documentation/problem-forwarding-to-keptn.md b/documentation/problem-forwarding-to-keptn.md index b27e15dc4..6252352aa 100644 --- a/documentation/problem-forwarding-to-keptn.md +++ b/documentation/problem-forwarding-to-keptn.md @@ -65,7 +65,8 @@ The dynatrace-service can [configure this feature automatically in a Dynatrace t **Notes** 1. The dynatrace-service requires a valid project to process problem events. We recommend always including a `KeptnProject` field set to a valid project in the custom notification integration payload definition. -2. Dynatrace alerting profiles can be used to filter certain problem types, e.g. infrastructure problems in production or slow performance in a developer environment. By creating a Keptn project to handle these remediation workflows and a Keptn service for each alerting profile, it is easy to define workflows for particular problem types. Furthermore, individual environment names such as `pre-prod` or `production` can be represented as stages within the project. +2. `sh.keptn.events.problem` open events without a stage cannot be processed and are discarded. +3. Dynatrace alerting profiles can be used to filter certain problem types, e.g. infrastructure problems in production or slow performance in a developer environment. By creating a Keptn project to handle these remediation workflows and a Keptn service for each alerting profile, it is easy to define workflows for particular problem types. Furthermore, individual environment names such as `pre-prod` or `production` can be represented as stages within the project. Here is a screenshot of a workflow triggered by a Dynatrace problem and how it then executes in Keptn: diff --git a/internal/problem/problem_event_handler.go b/internal/problem/problem_event_handler.go index cc0efff71..67b1744a9 100644 --- a/internal/problem/problem_event_handler.go +++ b/internal/problem/problem_event_handler.go @@ -121,6 +121,11 @@ func (eh ProblemEventHandler) HandleEvent() error { return eh.handleClosedProblemFromDT() } + if eh.event.GetStage() == "" { + log.Debug("Dropping open problen event as it has no stage") + return nil + } + return eh.handleOpenedProblemFromDT() } diff --git a/internal/problem/problem_event_handler_test.go b/internal/problem/problem_event_handler_test.go index 91f77dfff..d98d7b637 100644 --- a/internal/problem/problem_event_handler_test.go +++ b/internal/problem/problem_event_handler_test.go @@ -18,27 +18,35 @@ func TestProblemEventHandler_HandleEvent(t *testing.T) { tests := []struct { name string receivedEvent *cloudevents.Event + wantEmittedEvent bool expectedEmittedEvent *cloudevents.Event }{ { name: "open problem event", receivedEvent: readCloudEventFromFile("./testdata/open_problem/received_ce.json"), + wantEmittedEvent: true, expectedEmittedEvent: readCloudEventFromFile("./testdata/open_problem/expected_emitted_ce.json"), }, { name: "open problem event with tags", receivedEvent: readCloudEventFromFile("./testdata/open_problem_with_tags/received_ce.json"), + wantEmittedEvent: true, expectedEmittedEvent: readCloudEventFromFile("./testdata/open_problem_with_tags/expected_emitted_ce.json"), }, + { + name: "open problem event with no stage", + receivedEvent: readCloudEventFromFile("./testdata/open_problem_no_stage/received_ce.json"), + wantEmittedEvent: false, + }, { name: "closed problem event", receivedEvent: readCloudEventFromFile("./testdata/closed_problem/received_ce.json"), + wantEmittedEvent: true, expectedEmittedEvent: readCloudEventFromFile("./testdata/closed_problem/expected_emitted_ce.json"), }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - adapter, err := NewProblemAdapterFromEvent(*tt.receivedEvent) if !assert.NoError(t, err) { return @@ -50,8 +58,12 @@ func TestProblemEventHandler_HandleEvent(t *testing.T) { err = ph.HandleEvent() assert.NoError(t, err) - if assert.EqualValues(t, 1, len(kClient.eventSink)) { - assert.EqualValues(t, tt.expectedEmittedEvent, kClient.eventSink[0]) + if tt.wantEmittedEvent { + if assert.EqualValues(t, 1, len(kClient.eventSink)) { + assert.EqualValues(t, tt.expectedEmittedEvent, kClient.eventSink[0]) + } + } else { + assert.EqualValues(t, 0, len(kClient.eventSink)) } }) } diff --git a/internal/problem/testdata/open_problem_no_stage/received_ce.json b/internal/problem/testdata/open_problem_no_stage/received_ce.json new file mode 100644 index 000000000..a51364c78 --- /dev/null +++ b/internal/problem/testdata/open_problem_no_stage/received_ce.json @@ -0,0 +1,36 @@ +{ + "data": { + "ImpactedEntities": [ + { + "entity": "HOST-XXXXXXXXXXXXX", + "name": "MyHost1", + "type": "HOST" + }, + { + "entity": "SERVICE-XXXXXXXXXXXXX", + "name": "MyService1", + "type": "SERVICE" + } + ], + "ImpactedEntity": "Myhost1, Myservice1", + "KeptnProject": "shop", + "KeptnStage": "", + "KeptnService": "carts", + "PID": "99999", + "ProblemDetails": { + "id": "99999" + }, + "ProblemID": "999", + "ProblemTitle": "Dynatrace problem notification test run", + "ProblemURL": "https://example.com", + "State": "OPEN", + "Tags": "testtag1, testtag2" + }, + "id": "343cd015-72ac-4e10-b241-1136a22e4cd0", + "source": "dynatrace", + "specversion": "1.0", + "time": "2022-01-04T21:58:45.263Z", + "type": "sh.keptn.events.problem", + "shkeptncontext": "39393939-3920-4020-a020-202020202020", + "shkeptnspecversion": "0.2.3" +} \ No newline at end of file