Plugin Creators Overview

This document is an overview of plugin types.

The contents of this page refer to alpha features in Spinnaker 1.19.4.

This means we are working on their stability and usability, as well as possibly adding or changing features. Expect rough edges, and file issues as needed.

Note: Spinnaker 1.19.x only supports backend plugins due to a bug in Deck.

Requirements

  • Spinnaker v1.19.4+
  • Halyard 1.34+

Taxonomy

Extension Point: Defined by a Spinnaker service, it represents an official contract for which extensions can be written against. Defined by using an org.pf4j.ExtensionPoint interface. Written by Core Contributors.

Extension: A piece of code that implements an Extension Point. Written by Developers.

Plugin: A collection of Extensions that can be bundled together and shipped as a single artifact. Also written by Developers.

Plugin overview

A plugin enables an operator to extend Spinnaker with custom functionality. Use cases include fetching credentials from a custom authorization service, adding a wait stage to a pipeline, updating a Jira ticket, and sending Echo events to third-party tools.

ExtensionPoint plugins

Spinnaker uses the Plugin Framework for Java (PF4J) to indicate an extension point interface to a service. You can create a plugin that implements the methods declared in an extension point. Creating a plugin based on an extension point has a number of advantages:

  • It’s the easiest - use the @Extension annotation and implement the methods declared in your chosen extension point
  • Spinnaker loads the plugin in an isolated classpath
  • It has the least amount of maintenance work
  • Updates to Spinnaker are not likely to break your plugin

Finding an extension point

An extension point is an interface that extends org.pf4j.ExtensionPoint and is located in the api module of a service. Spinnaker exposes the following extension points:

Look through the code or ask in the Spinnaker Slack to find extension points not listed here.

Example ExtensionPoint plugin

The pf4jStagePlugin creates a custom pipeline stage that waits a specified number of seconds before signaling success. Consult the Pipeline Stage Plugin Walkthrough for a detailed explanation of this plugin.

Interface (Non-ExtensionPoint) plugins

The second way you can create a plugin is to implement a regular Java interface that you find in a service. Your plugin uses the PF4J @Extension annotation but does not extend org.pf4j.ExtensionPoint.

Advantages:

  • Spinnaker loads the plugin in an isolated classpath

Disadvantages:

  • Requires a moderate knowledge of Spinnaker’s architecture and code
  • Plugin can break if the service’s interface changes

Example Interface plugin

The pf4jPluginWithoutExtensionPoint plugin extends the functionality of Kork’s SecretEngine . SecretEngine is a regular Java interface that does not import any PF4J classes. pf4jPluginWithoutExtensionPoint’s SillySecretEngine implements SecretEngine and uses the @Extension annotation to identify itself as a PF4J plugin. See the plugin project’s README and code for details on how this plugin works.

Spring plugins

When you can’t find an org.pf4j.ExtensionPoint to use or a Java interface to implement, you can create a plugin using Spring. This is should be done as a last resort, since the disadvantages outweigh the advantages.

Advantages:

  • Full control

Disadvantages:

  • Requires an expert knowledge of Spinnaker’s architecture and codebase
  • Requires working knowledge of Spring
  • High maintenance; plugin can break when Spinnaker dependencies and functionality change

Example Spring plugin

The Spring Example Plugin does not use a PF4J extension point or dependencies. It uses Spring components and was created to test various use cases. See the project for details.

Last modified February 3, 2022: docs(fix): fix broken link to Stage Plugin Walkthrough (#176) (9904847)