The last project you’ll create manually

how to automate your boilerplate tailor-made to your needs

Matan Golan
Dec 1 · 6 min read

The world of micro-services changed the way developers think, code and manage their workspaces, suddenly new services popup on a weekly basis. When I started working at SecureNative the roadmap was pretty clear, we’ll need to manage thousands of different micro-services, sprint after sprint I was doing the same job for every new micro-service. So I started looking for tools to automate this tedious process, some had a steep learning curve, some didn’t work for us (feature-wise) and some were very opinionated.

So we did what developers does best, write a piece of code to automate it. Two weeks later packman was born, packman is a cli-tool built with extensibility and simpleness in mind, we use it intensively at SecureNative for the past 8 months and we have a wide range of templates that solves different problem.

In this article I’ll try to explain to you what is packman and even more important how it works… we’ll do it Tarantino-style, breaking it into unrelated parts hoping that you get a closure at the end of this article :)

Part 1: The Template Engine

Photo by Mockaroon on Unsplash

Apparently GO has a pretty great template engine in its standard library, it’s so simple and powerful that I better start with examples of how to use it:

This function will template the input text for a given data map, the map acts as the template data and we can use this data to create smarter templates.

In this article I’ll cover only three of GO’s template engine features but knowing them should give you a great starting point.

Feature 1 — Variable Substitution:

The most elementary part of any template engine is to substitute variables, for example, for the following template file:

Hello {{{ .Name }}},This is a template which prints your name, hurray!

and the following data:

the template engine will return:

Hello Matan Golan,This is a template which prints your name, hurray!

Easy stuff right? wait it’s getting interesting…

Feature 2 — Condition Blocks:

Substituting variables is nice but what if we have to add code only if certain condition is met?

Hello {{if .Name}} {{.Name}} {{else}} there {{end}},
This is a template which prints your name, hurray!

now the template engine will print the name only if the name exists, otherwise it will just print Hello there,

Feature 3 — Ranges:

Now let’s add a shopping cart to the template, we’ll start from the data schema this time:

and we’ll modify the above template to look like this:

Hello {{if .Name}} {{.Name}} {{else}} there {{end}},
This is your shopping cart:
{{{ range .Cart }}}
- {{{ .Name }}} ({{{ .Price }}}$)
{{{ end}}

which will result in:

Hello Matan Golan,
This is your shopping cart:
- Sunglasses (199$)
- Jetpack (599$)

Cool right? and believe me it’s just the tip of the iceberg, if your’e interested in other features of GO’s template engine, please check this excellent cheatsheet:

As you might have guessed packman uses this template engine since we aren’t in the mood of re-inventing the wheel :)

Part 2: The Script

Photo by Markus Spiske on Unsplash

If you’ve read the last part you probably know that we need a way to feed the template engine with data. When designing packman we had only one thing in mind, we don’t want you to learn anything new! Your’e a developer, you know how to code and we want you to use what you’ve already know.

The script is written by you, the template owner, and it has only one purpose, to generate the data model. Later on packman will use this data model to feed the template engine.

To avoid from choosing a specific scripting language, packman is (in theory) able to call any kind of process that can write a json file; that’s right, packman and your script will communicate through temporary files.

When executing your script packman will add 2 additional cli-arguments: the first one is the path to a file containing the input flags of your script and the second one is a path which packman expects you to write the data model file to. Packman will parse your reply and pass it to the template engine.

One example is worth a thousand words:

Part 3 — Where do templates come from?

Photo by Gareth Davies on Unsplash

Ok, so we have templates and scripts where do we put them? the answer is simple: git! why git? because every developer knows how to work with git, you get full version control, branches, pull request and eventually there is no difference between developing a template and developing any other project.

So your templates will be cloned from any git hosting service (Github, Gitlab, BitBucket, etc …) allowing you to share it easily, making it private, make code reviews or use any kind of work methodology you are comfortable with.

Part 4 — The Packman

Photo by chuttersnap on Unsplash

What have we learned so far?

  1. Packman is using GO’s template engine, you can use it to template your files however you want.
  2. The template engine needs to be fed with data, the template script will generate the data based on your needs, it could parse a protobuf/swagger files, it can be static configuration or even check the weather :)
  3. The template files are stored on any git host.

Now, it’s time to see how all parts gets together to compose packman, again a picture worth a thousand words:

Architectural Overview of packman

packman has several commands in its toolchain but the most important one is unpack. for example the following command:

packman unpack \
https://github.com/securenative/packman-init \
myProject \
-author matan \
-company SecureNative

will clone the template project from “https://github.com/securenative/packman-init” to a local folder called “myProject” passing two flags to the template script (author and company). You can treat these flags as the input of your template and you can have as many flags as you want.

These flags are being written as a json file to a temporary location on your hard-drive and meant to be read by your script.

Then, packman will run your script with two arguments the path to the flags file and the path to save the reply to. Your script runs and suppose to write its data-model to the provided path so packman can read it and feed the template engine with it.

Now packman simply walks on your project file tree, applying the template engine on each one of your files and voila, your’e left with the generated project. Amazing isn’t it?

packman sample project that just emits the input flags on a README file

Part 5 — What’s now?

Photo by Javier Allegue Barros on Unsplash

First of all, we hope that you liked packman and you’ll give it a try; Rest assured that we will continue to develop packman giving it more capabilities and features that makes your workflow simpler.

If you want a real world example you can check out our protobuf example which takes a protobuf file and generates all the boilerplate needed from it, or you can just read the next part which explains how we’ve built it.

And as always, you can give us a hand! packman is an open-source project and we will be more than happy to get any kind of feedback on it.

Happy Templating!

SecureNative

SecureNative engineering blog

Thanks to Amit Bourmad

Matan Golan

Written by

Software Architect @ SecureNative

SecureNative

SecureNative engineering blog

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade