Skip to content

Commit

Permalink
feat(notifications): add NotificationAgent extension point (#962)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielpeach committed Jul 15, 2020
1 parent d3c50cf commit 50c86c3
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2020 Armory, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.netflix.spinnaker.echo.api.events;

import com.netflix.spinnaker.kork.annotations.Alpha;
import com.netflix.spinnaker.kork.plugins.api.internal.SpinnakerExtensionPoint;
import java.util.Map;
import javax.annotation.Nonnull;

/** A NotificationAgent handles user-configured pipeline notifications. */
@Alpha
public interface NotificationAgent extends SpinnakerExtensionPoint {
/** The notification's type (e.g., Slack, SMS, email). */
@Nonnull
String getNotificationType();

/**
* @param notificationConfig - User-defined configuration. Arbitrary key-value pairs can be passed
* to the agent here (e.g., a Slack channel name).
* @param application - The name of the application where the pipeline was run.
* @param event - a Spinnaker {@link Event}.
* @param status - The state of the referenced resource (e.g., failed, complete, etc.).
*/
void sendNotifications(
@Nonnull Map<String, Object> notificationConfig,
@Nonnull String application,
@Nonnull Event event,
@Nonnull String status);
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,14 @@ package com.netflix.spinnaker.echo.notification
import com.fasterxml.jackson.databind.ObjectMapper
import com.netflix.spinnaker.echo.api.events.EventListener
import com.netflix.spinnaker.echo.api.events.Event
import com.netflix.spinnaker.echo.services.Front50Service
import com.netflix.spinnaker.echo.jackson.EchoObjectMapper
import groovy.util.logging.Slf4j
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value

@Slf4j
abstract class AbstractEventNotificationAgent implements EventListener {

@Autowired
Front50Service front50Service

@Autowired(required = false)
protected ObjectMapper mapper
protected ObjectMapper mapper = EchoObjectMapper.getInstance()

@Value('${spinnaker.base-url}')
String spinnakerUrl
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2020 Armory, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.netflix.spinnaker.echo.notification;

import com.netflix.spinnaker.echo.api.events.Event;
import com.netflix.spinnaker.echo.api.events.NotificationAgent;
import java.util.Map;

public class ExtensionNotificationAgent extends AbstractEventNotificationAgent {

private final NotificationAgent agent;

public ExtensionNotificationAgent(NotificationAgent agent) {
this.agent = agent;
}

@Override
public String getNotificationType() {
return agent.getNotificationType();
}

@Override
public void sendNotifications(
Map notification, String application, Event event, Map config, String status) {
agent.sendNotifications(notification, application, event, status);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2020 Armory, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.netflix.spinnaker.echo.plugins

import com.netflix.spinnaker.echo.api.events.Event
import com.netflix.spinnaker.echo.api.events.NotificationAgent
import org.pf4j.Extension

@Extension
class NotificationAgentExtension : NotificationAgent {
override fun getNotificationType() = "extension_notification"
override fun sendNotifications(notification: MutableMap<String, Any>, application: String, event: Event, status: String) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package com.netflix.spinnaker.echo.plugins.test
import com.netflix.spinnaker.echo.Application
import com.netflix.spinnaker.echo.plugins.EchoPlugin
import com.netflix.spinnaker.echo.plugins.EventListenerExtension
import com.netflix.spinnaker.echo.plugins.NotificationAgentExtension
import com.netflix.spinnaker.kork.plugins.SpinnakerPluginManager
import com.netflix.spinnaker.kork.plugins.internal.PluginJar
import com.netflix.spinnaker.kork.plugins.tck.PluginsTckFixture
Expand All @@ -40,7 +41,8 @@ class EchoPluginsFixture : PluginsTckFixture, EchoTestService() {
final override val versionNotSupportedPlugin: PluginJar

override val extensionClassNames: MutableList<String> = mutableListOf(
EventListenerExtension::class.java.name
EventListenerExtension::class.java.name,
NotificationAgentExtension::class.java.name
)

final override fun buildPlugin(pluginId: String, systemVersionRequirement: String): PluginJar {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.netflix.spinnaker.echo.plugins.test

import com.netflix.spinnaker.echo.api.events.EventListener
import com.netflix.spinnaker.echo.api.events.NotificationAgent
import com.netflix.spinnaker.kork.plugins.tck.PluginsTck
import com.netflix.spinnaker.kork.plugins.tck.serviceFixture
import dev.minutest.rootContext
Expand All @@ -41,6 +42,15 @@ class EchoPluginsTest : PluginsTck<EchoPluginsFixture>() {
that(extension).isNotNull()
}
}

test("Notification agent extension is loaded into context") {
val eventListeners = applicationContext.getBeansOfType(NotificationAgent::class.java)
val extensionBeanName = "com.netflix.echo.enabled.plugin.NotificationAgentExtension".replace(".", "")
val extension = eventListeners[extensionBeanName]
expect {
that(extension).isNotNull()
}
}
}
}
}
2 changes: 2 additions & 0 deletions echo-web/echo-web.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ dependencies {
implementation "com.netflix.spinnaker.fiat:fiat-core:$fiatVersion"
implementation "org.springframework.boot:spring-boot-starter-web"
implementation "org.springframework.boot:spring-boot-starter-actuator"
implementation "com.netflix.spinnaker.kork:kork-artifacts"
implementation "com.netflix.spinnaker.kork:kork-core"
implementation "com.netflix.spinnaker.kork:kork-config"
implementation "com.netflix.spinnaker.kork:kork-web"
implementation "com.squareup.retrofit:retrofit"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,18 @@

import com.netflix.spinnaker.config.PluginsAutoConfiguration;
import com.netflix.spinnaker.echo.api.events.EventListener;
import com.netflix.spinnaker.echo.api.events.NotificationAgent;
import com.netflix.spinnaker.echo.events.EventPropagator;
import com.netflix.spinnaker.echo.notification.ExtensionNotificationAgent;
import com.netflix.spinnaker.kork.artifacts.parsing.DefaultJinjavaFactory;
import com.netflix.spinnaker.kork.artifacts.parsing.JinjaArtifactExtractor;
import com.netflix.spinnaker.kork.artifacts.parsing.JinjavaFactory;
import com.netflix.spinnaker.kork.core.RetrySupport;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.ApplicationContext;
Expand All @@ -47,11 +54,19 @@ public EchoCoreConfig(ApplicationContext context) {
}

@Bean
public EventPropagator propagator() {
public EventPropagator propagator(Optional<List<NotificationAgent>> notificationAgents) {

EventPropagator instance = new EventPropagator();
for (EventListener e : context.getBeansOfType(EventListener.class).values()) {
instance.addListener(e);
}
val extensionNotificationAgents =
notificationAgents.orElseGet(ArrayList::new).stream()
.map(ExtensionNotificationAgent::new)
.collect(Collectors.toList());
for (ExtensionNotificationAgent e : extensionNotificationAgents) {
instance.addListener(e);
}
return instance;
}

Expand Down

0 comments on commit 50c86c3

Please sign in to comment.