It’s been a while since I thought about writing about software automation, today is the day.
Who knows me, knows that I like to automate most of the repetitive and time consuming tasks, this is specially true in the software development process, this leaves me with more time to get to what really matters, solving problems, deliver quality software and what for me is the main motivation for writing software, make the world a better place, be it building even more automation so people can spend time doing what they really want and like to do, or by creating new ways to be more efficient at a task, but I digress…
I will focus on the software development and deployment lifecycle since that’s what I work with the most daily. Until a “better mousetrap” comes up I usually stick to the same tools, after all they were already tried and tested.
Here are some of them:
- Software builds, releases and deployments – Jenkins
- Infrastructure management – Terraform.
- Configuration Management – Saltstack
- Other tools I’m currently evaluating are rundeck and node red.
Software builds, releases and deployments
In order to easily keep an eye on the compilation and test status of pull requests and currently being developed features, my main choice is Jenkins, TeamCity is also a good option, but I believe that Jenkins has more plugins and integrations, but please feel free to prove me wrong. The addition of pipelines allowing to have builds per PR and branch was a huge improvement. This leaves the developer free to finish his feature without worrying if everything passes, of course he should still ensure new tests are ok, but the old ones can be run only after the feature is finished, such will be the case for regressions for example, so less time is wasted waiting for tests.
Since I mainly work with Java the release builds and deployment to a Maven repository is completely automated, all I need is a job that monitors the release branch and when there is anything new the build and deploy runs (through Maven) this makes closing the release a faster process since there is no need to wait for artifact upload. Other option is to finish the release with Jenkins but I have yet to find a way to deal with conflicts when merging to develop.
Finally deployments are done either on a job that is triggered manually or can even be automatic after the build of the release is done. Another big advantage of this automation is that there are no more instructions on how to make a deployment, it’s automated and always the same so there can be no human made errors, well there can, after all the deployment job is created by a humam, hence the need to test the automations themselves. Other option may be RunDeck but it’s still under evaluation, the feature of being able to schedule when the jobs run sounds great specially if your deployment is not redundant (yet) and needs to be done at times like 3am when there is little to no usage in order to avoid impact, and since it’s all automated nobody needs to sacrifice sleep hours, but please don’t do this without proper monitoring and alarms if something goes bad (beware Murphy’s law).
For infrastructure I have yet to find a better alternative to Terraform, being able to describe everything in code and then create all it’s needed is the best approach for me, using modules I can specify the entire stack for the software and easily create mutiple environments, production, pre-production, QA, etc. I can even rebuild everything if something goes horribly wrong.
How good is infrastructure if it’s not configured? In the days of Docker Kubernetes and containers everywhere, for some deployments I still prefer more classic approaches. Just a server (or 10, or 100 that’s the beauty of automation) with the software directly deployed there. You also need to provide access to some environments to developers so they can investigate on more complicated bugs. For this I work with Saltstack, when I was looking at a configuration management tool I evaluated others like Puppet, Ansible and Chef, and at the time it seemed like the easiest one to work with. I had to work with Puppet on a company and found it quite hard to do everything, but then there was already an established system (RedHat Satellite was in the mix) so I won’t blame the tool itself maybe it was just the way it was being used, until I get more time to research on it I can’t tell. To make everything simpler I also use Packer to pre-build system images mainly for AWS this allows me to preinstall a JRE or other needed software, this makes it so that Salt only has to deal with application specific configurations and user management as most software is pre-installed.
Salt also allows to create “modules” in some cases I have a state file that if configurations for Let’s Encrypt exist Certbot is automatically installed and the certificates requested, as well as renewal scripts.
Then with a few lines of code I can declare the new configuration, push to the production branch and it is automatically applied after a few minutes. Other advantage is that if someone messes with a configuration file as long as salt is managing it, it will be updated to the correct state.
But this comes with a cost, if I ever need to do a quick test by changing configuration Salt will overwrite what I am changing, so I must remember to stop it before any changes are made, and start it again when I’m done, failing to do so will cause problems either because my configurations are reset to the ones defined in Salt, or they may become inconsitent since the Salt Minion is not started again it will not apply the changes. I thought about adding a script to ensure the Salt Minion is running, but then I would need to disable that one along with Salt itself, it will only add complexity and more failure points.
Docker is another one, at the moment I use it mostly for development environments, reducing the need of configuration on the developer computer. I think the only thing the developer should have to install on his computer is the IDE and in some cases the compiler/runtime for the language he is working with here are a few examples:
- Databases – Either pre-configured or the more raw official containers.
- Server Software – Be it a set of NGINX, and PHP for WordPress or other PHP app, or a Wildfly to deploy a webapp.
For deployments, it’s also a good option, everything is packaged in the container and you don’t need to worry about much, I still have to create a decent workflow for that use case.
Maven Wrapper is something similar to the Gradle wrapper that almost every Android project uses, but for Maven, the main advantage here is to ensure that every developer will not need to install it, and that everyone uses the same version, one example of this need is building webapps with Thorntail as the plugin does not work with Maven 3.6.0.
And that’s it! These are my tools of choice for automation, others exist and may be better, for now I’m evaluating two others, as I wrote before RunDeck is one of them, mostly to automate tasks like deployments, or restarting services as a way of first trying to fix emerging issues and allowing someone with less technical knowledge on how to do it simply pressing a button. Provisioning new environments on demand is also a possibility I can think of.
The second one is Node-Red quite interesting for quick wiring of systems, maybe for custom automations that may need adjustments over time, or more quick integrations that may not need to be as scalable. For now it will stay in consideration for future challenges since I don’t feel the need for it now.