From 9df646ff70d14b522afd676e87c1a4a35ca30bd2 Mon Sep 17 00:00:00 2001 From: "GARCIA, JOSE" Date: Tue, 15 Oct 2024 12:21:12 -0700 Subject: [PATCH] fix(notifications/cdEvents): Fixed CDEvents notification for ManualJudgment --- .../AbstractEventNotificationAgent.java | 59 ++++++++++++++++++- .../AbstractEventNotificationAgentSpec.groovy | 18 ++++++ 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/echo-core/src/main/java/com/netflix/spinnaker/echo/notification/AbstractEventNotificationAgent.java b/echo-core/src/main/java/com/netflix/spinnaker/echo/notification/AbstractEventNotificationAgent.java index b0742b2c3..85126a6e3 100644 --- a/echo-core/src/main/java/com/netflix/spinnaker/echo/notification/AbstractEventNotificationAgent.java +++ b/echo-core/src/main/java/com/netflix/spinnaker/echo/notification/AbstractEventNotificationAgent.java @@ -46,6 +46,13 @@ public abstract class AbstractEventNotificationAgent implements EventListener { .put(STAGE, ImmutableMap.of("type", STAGE, "link", "stage")) .build(); + private static final Map MANUAL_JUDGMENT_CONDITIONS = + ImmutableMap.builder() + .put(ManualJudgmentCondition.MANUAL_JUDGMENT.getName(), StageStatus.STARTING.getName()) + .put(ManualJudgmentCondition.CONTINUE.getName(), StageStatus.COMPLETE.getName()) + .put(ManualJudgmentCondition.STOP.getName(), StageStatus.FAILED.getName()) + .build(); + private final Logger log = LoggerFactory.getLogger(getClass()); protected ObjectMapper mapper = EchoObjectMapper.getInstance(); @@ -182,9 +189,11 @@ private boolean shouldSendRequestForNotification( if (when != null) { String requiredWhen = format("%s.%s", configType, status); if (when instanceof String) { - return ((String) when).contains(requiredWhen); + return isManualJudgmentMatchStringCase((String) when, status) + || ((String) when).contains(requiredWhen); } else if (when instanceof Collection) { - return ((Collection) when).contains(requiredWhen); + return isManualJudgmentMatchCollectionCase((Collection) when, status) + || ((Collection) when).contains(requiredWhen); } } } @@ -199,6 +208,52 @@ private boolean contentKeyAsBoolean(Event event, String key) { return Boolean.parseBoolean(value.toString()); } + enum StageStatus { + COMPLETE("complete"), + STARTING("starting"), + FAILED("failed"); + + final String name; + + StageStatus(String name) { + this.name = name; + } + + String getName() { + return this.name; + } + } + + enum ManualJudgmentCondition { + CONTINUE("manualJudgmentContinue"), + STOP("manualJudgmentStop"), + MANUAL_JUDGMENT("manualJudgment"); + + final String name; + + ManualJudgmentCondition(String name) { + this.name = name; + } + + String getName() { + return this.name; + } + } + + private static boolean isManualJudgmentMatchStringCase(String when, String status) { + return status.equals(MANUAL_JUDGMENT_CONDITIONS.get(when)); + } + + private static boolean isManualJudgmentMatchCollectionCase( + Collection when, String status) { + for (String condition : when) { + if (status.equals(MANUAL_JUDGMENT_CONDITIONS.get(condition))) { + return true; + } + } + return false; + } + private static boolean isExecution(String type) { return "pipeline".equals(type) || "orchestration".equals(type); } diff --git a/echo-core/src/test/groovy/com/netflix/spinnaker/echo/notification/AbstractEventNotificationAgentSpec.groovy b/echo-core/src/test/groovy/com/netflix/spinnaker/echo/notification/AbstractEventNotificationAgentSpec.groovy index a0f1de925..5bf4bfd63 100644 --- a/echo-core/src/test/groovy/com/netflix/spinnaker/echo/notification/AbstractEventNotificationAgentSpec.groovy +++ b/echo-core/src/test/groovy/com/netflix/spinnaker/echo/notification/AbstractEventNotificationAgentSpec.groovy @@ -93,6 +93,24 @@ class AbstractEventNotificationAgentSpec extends Specification { fakeStageEvent("orca:stage:complete", "stage.complete", false, true) || 0 } + @Unroll + def "sends notifications for ManualJudgment stage based on status and configuration"() { + given: + subclassMock.sendNotifications(*_) >> { notification, application, event_local, config, status -> } + + when: + agent.processEvent(event) + + then: + expectedNotifications * subclassMock.sendNotifications(*_) + + where: + event || expectedNotifications + fakeStageEvent("orca:stage:complete", "manualJudgmentContinue") || 1 + fakeStageEvent("orca:stage:starting", "manualJudgment") || 1 + fakeStageEvent("orca:stage:failed", "manualJudgmentStop") || 1 + } + private def fakePipelineEvent(String type, String status, String notifyWhen, Map extraExecutionProps = [:]) { def eventProps = [ details: [type: type],