Figuring Out Spinnaker Pipeline Expressions

spinnaker, kubernetes comments edit

I’m using Spinnaker to manage microservice deployments in one of my projects. One of the nice features in Spinnaker is pipeline expressions - a way to do a little dynamic calculation based on the current state of the pipeline.

I’m somewhat new to Spinnaker and I just got through trying to figure out a way to do some conditional stage execution using pipeline expressions but found the learning curve was steep. I don’t plan on repeating everything already in the docs… but hopefully I can help you out.

The Layers: Spinnaker pipeline expressions use the Spring Expression Language syntax to expose the currently executing Spinnaker pipeline object model along with some whitelisted Java classes so you can make your pipeline stages more dynamic.

That’s a lot to build on: The Spinnaker object model, Spring Expression Language, and Java. If you’re, say, a Node or .NET developer, it’s a bit of an uphill battle.

Resources:

The Data: The best way you can see what pipeline data you have available is to run a pipeline. Once you have that, expand the pipeline and click the “Source” link in the bottom right. That will get you a JSON document.

Get the pipeline source

The JSON doc is an “execution.” In there you’ll see the “stages” each of which has a “context” object. This is the stuff you’ll get when you use the helper functions like #stage("My Stage") - it’ll find the JSON stage in the execution with the appropriate name and expose the properties so you can query them.

Troubleshooting: There are two ways I’ve found to troubleshoot.

  1. Create a test pipeline. Actually just run the expression in a test pipeline. You’ll get the most accurate results from this, but you may not be able to test the queries or operations against a “real pipeline execution” this way.
  2. Use the REST API. Spinnaker has a REST API and one of the operations on a pipeline is evaluateExpression. This runs against already-complete executions but is the fastest way to iterate over most queries. I’ll show you how to use that.

If you want to use the REST API to test an expression, first find a pipeline execution you want to use for testing. As with earlier, go get the JSON doc for a pipeline run by clicking the “Source” link on a complete pipeline. Now look at the URL. It’ll look like http://spin-api.your.com/pipelines/01CMAJQ6T8XC0NY39T8M3S6906. Grab that URL.

Now with your favorite tool (curl, Postman, etc.)…

  • Create a POST request to the evaluateExpression endpoint for that pipeline, like: http://spin-api.your.com/pipelines/01CMAJQ6T8XC0NY39T8M3S6906/evaluateExpression
  • In the body of the request, send a single parameter called expression. The value of expression should be the expression you want to evaluate, like ${ 1 + 1 } or whatever.
  • The response will come back with the result of the expression, like { result: 2 }. If you get an error, read the message carefully! The error messages will usually help you know where to look to solve the issue. For example, if you see the error Failed to evaluate [expression] EL1004E: Method call: Method length() cannot be found on java.util.ArrayList type - you know that whatever you’re calling length() on is actually an ArrayList so go look at the ArrayList documentation and you’ll find out it’s size() not length(). The errors will help you search!

Example: The pipeline expression I wanted was to determine if any prior step in the pipeline had a failure. The expression:

${ #stage("My Stage").ancestors().?[status.isFailure() && name != "My Stage"].isEmpty() }

Let’s walk through how I got there.

How did I figure all that out? Lots of trial and error, lots of poking around through the source. That REST API evaluation mechanism was huge.

Comments