Zapp: Runbook Automation
Tags: perl, mojolicious
Published: 2021-07-29 00:08:12

{% github preaction/zapp no-readme %}

I hate runbooks. I've been an SRE from since we were called webmasters. In all this time, the least helpful part of my job has been the lists of commands to run when there's a problem. Often out-of-date, frequently lacking in context, and altogether useless when production is burning around you and clients are banging on the door. I'm a programmer. I don't perform tedious tasks, I automate them. Why, then, should I like documenting tedious tasks?

I hate [Jenkins](https://www.jenkins.io). No, that's not quite true. I'm disappointed in Jenkins. Parameterized builds could be such a useful tool, but the input form they provide the end-user is ugly at best, incomprehensible at worst. Jenkins's pipeline syntax opens the door to some truly amazing abilities, but there's no way for me to package those abilities in a way I can simply give to someone without training them on how to navigate Jenkins's UI.

To solve these problems, I wrote [Zapp](https://metacpan.org/pod/Zapp). In Zapp, I can create a plan as a series of tasks, like a Jenkins build. Plans can have input fields, like a Jenkins parameterized build. Users can then run the plan and see the output.

[Zapp tasks](https://metacpan.org/pod/Zapp::Task) can be more than a shell command or script. Zapp tasks have their own configuration, so I can provide a friendly form for the user to control what the task will do. Additionally, tasks output typed data that can be used as input to subsequent tasks. When the task executes, it can render its own output to show the end-user what is happening.

So, I can create a plan that asks a user to input their credentials.
￼![Zapp form showing two inputs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oju8cu23smeu63n50cgz.png)

Then, the plan can fetch an authentication token using those credentials.
￼![Zapp form for GetOAuth2Token task](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3lc9csiticip0wwy3k3r.png)

Finally, with this authentication token, I can perform my request.
￼![Zapp form for Request task](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l3ar28jn017sgj4hso64.png)

Then when I want to run the plan, I can input my credentials and hit a button. 
￼![Zapp form to run the plan](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uicug5womej7sklgvc4w.png)

As the job runs, it updates the job page. If any errors occur, the job stops and the failing task shows an error message. I can choose to re-play the job, or I can go back and fix whatever problem there is.

Zapp isn't limited to automating runbooks. Zapp provides webhook triggers to perform plans automatically. Build your software after a commit is pushed to Github, respond to Slack commands, or (when a future version adds scheduled tasks) run a nightly SQL report. Not only are these tasks automated, but they are easy to configure so that users can support themselves.

Finally, if Zapp can't do what you want, you can write your own task classes to perform tasks, type classes to accept input from users, and trigger classes to run plans automatically in response to events. Zapp is written in modern Perl using the Mojolicious web framework and the Minion task runner.

With Zapp, I can make tedious support processes into a single web form, or even a single click. As needs change, processes can be tweaked using a friendly UI. And new types of tasks can be created to provide ever more options for your users.

Zapp is very much Alpha-grade software right now: I use it personally, but there are bugs and missing features yet. The plugin APIs are pretty solid, though, so you can write your own tasks, types, and triggers. There are a lot of features that Minion provides that Zapp does not yet take advantage of, so there's plenty of possibilities for future development. If you have any questions, suggestions, issues, or want to know if Zapp can work for you, feel free to let me know at doug@preaction.me or on [irc.libera.chat in #mojo-yancy](https://web.libera.chat/#mojo-yancy).