The Zen of Ansible
The Zen of Ansible
This blog post is based on my presentation at AnsibleFest 2022 in Chicago and virtually.
Recently, a suggestion was made to adopt Tim Peters' "The Zen of Python" as an overall guiding principle for designing good automation content. That gave me pause because it didn't seem like the right thing to me. While there is definitely some very good advice to "The Zen of Python" that can be applied to Ansible content, adopting it in its entirety would not provide the best user experience that Ansible is capable of and known for. Its presence as a guiding principle for content design gives the wrong impression and re-enforces a mindset we don't want to recommend.
This got me thinking, what is "the zen" of Ansible?
I considered the spirit of "The Zen of Python" and then I returned to the Ansible best practices talk that I first co-presented back in 2016 at Red Hat Summit. In that talk, I said that Ansible was designed with a philosophy of sorts from the very beginning.
"The Ansible way" is to provide an automation tool that is simple, powerful and agentless. Ansible enables users with no special coding skills to do powerful things across multiple IT domains. Its human readable automation can be utilized and shared by every IT team so they can get productive quickly and contribute their expertise. Its agentless architecture provides the flexibility to be applied across all IT infrastructure domains.
It is this thinking behind its design that everything in this post relates back to in one way or another.
Besides "The Zen of Python" and my Ansible best practices talk, I also considered what I've heard talking to hundreds of you in my many years within the Ansible ecosystem. What I came up with are these 20 aphorisms for Ansible.
- Ansible is not Python.
- YAML sucks for coding.
- Playbooks are not for programming.
- Ansible users are (most likely) not programmers.
- Clear is better than cluttered.
- Concise is better than verbose.
- Simple is better than complex.
- Readability counts.
- Helping users get things done matters most.
- User experience beats ideological purity.
- "Magic" conquers the manual.
- When giving users options, use convention over configuration.
- Declarative is better than imperative -- most of the time.
- Focus avoids complexity.
- Complexity kills productivity.
- If the implementation is hard to explain, it's a bad idea.
- Every shell command and UI interaction is an opportunity to automate.
- Just because something works, doesn't mean it can't be improved.
- Friction should be eliminated whenever possible.
- Automation is a journey that never ends.
Your Ansible automation content doesn't necessarily have to follow this guidance, but they're good ideas to keep in mind. These aphorisms are opinions that can be debated and sometimes can be contradictory. What matters is that they communicate a mindset for getting the most from Ansible and your automation.
Let me take you deeper into each of the aphorisms and explain what they mean to your automation practice.
Ansible is not Python. YAML sucks for coding. Playbooks are not for programming. Ansible users are (most probably) not programmers.
These aphorisms are at the heart of why applying guidelines for a programming language to good Ansible automation content didn't seem right to me. As I said, it would give the wrong impression and would reinforce a mindset we don't recommend -- that Ansible is a programming language for coding your playbooks.
These aphorisms are all saying the same thing in different ways -- certainly the first 3. If you're trying to "write code" in your plays and roles, you're setting yourself up for failure. Ansible's YAML-based playbooks were never meant to be for programming.
So it bothers me when I see Python-isms bleeding into what Ansible users see and do. It may be natural and make sense if you write code in Python, but most Ansible users are not Pythonistas. So, it can be challenging and confusing when these isms are incorporated, thereby introducing friction that degrades their user experience and the value that Ansible provides.
By Ansible not being a programming language, all parts of your organization can contribute to automating your entire IT stack rather than relying on skill programmers to understand your operations to write and maintain code for it.
If you are a programmer creating Ansible modules and plugins, assume you are not the target audience for what you are developing and your target audience won't have the same skills and resources you possess.
Clear is better than cluttered. Concise is better than verbose. Simple is better than complex. Readability counts.
These are really just interpretations of aphorisms in "The Zen of Python". The last one is taken directly from it because you can't improve on perfection.
In the original Ansible best practices talk, we recommended users optimize for readability. This holds true even more so today. If done properly, your content can be the documentation of your workflow automation. Take the time to make your automation as clear and concise as possible. Iterate over what you create and always look for opportunities to simplify and clarify.
These aphorisms don't just apply to those writing playbooks and creating roles. If you are a module developer, think about how your work can assist users, be clear and concise, do things simply and just get things done.
Helping users get things done matters most. User experience beats ideological purity.
Whether you are creating modules, plugins and collections or writing playbooks or designing a cross domain hybrid automation workflow -- Ansible is for helping you get things done. Always consider and look to maximize the user experience. Don't get caught up and beholden to some strict interpretation of standards or ideological purity that shifts the burden on the end user.
"Magic" conquers the manual.
Arthur C. Clarke wrote, "Any sufficiently advanced technology is indistinguishable from magic."
The "magic" in Ansible is its playbook engine and module system. It is how Ansible provides powerful and flexible capabilities in a straightforward and accessible way by abstracting users from all of the complex implementation details that lie beneath. This frees users from doing time consuming and error prone manual operations or writing brittle one-off scripts and code, enabling them the time to put their valuable expertise to use where it is needed.
Design automation that amazes users can make difficult or tedious tasks easy and almost effortless. Look to provide powerful time saving capabilities that are quick to deploy and utilize them to get things done.
When giving users options, use convention over configuration.
I am a big proponent of convention over configuration and don't think it gets enough consideration in the Ansible community. Convention over configuration is a design paradigm that attempts to decrease the number of decisions that a developer is required to make without necessarily losing flexibility so they don't have to repeat themselves. It was popularized by Ruby on Rails.
A playbook developer utilizing your work should only need to specify unique and unconventional aspects of their automation tasks and workflows and no more. Look to reduce the number of decisions and implementation details a user needs to make. Take the time to handle the most common use cases for them. Look to provide as many sensible defaults with modules, plugins and roles as possible. Optimize for users to get things done quickly.
Declarative is better than imperative -- most of the time.
This aphorism is particularly for Ansible Content Collection developers. Ansible is a desired state engine by design. Think declaratively first. If there truly is no way to design something declaratively, then use imperative (procedural) means.
Declarative means that configuration is guaranteed by a set of facts instead of by a set of instructions, for example, "there should be 10 RHEL servers", rather than "depending on how many RHEL servers are running, start/stop servers until you have 10, and tell me if it worked or not".
This aphorism is an example of the "user experience beats ideological purity" aphorism in practice. Rather than strictly adhering to a declarative approach to automation, Ansible incorporates declarative and imperative means. This mix offers you the flexibility to focus on what you need to do, rather than strictly adhere to one paradigm.
Focus avoids complexity. Complexity kills productivity.
Remember that complexity kills productivity. The Ansible team at Red Hat really means it and believes that. That's not just a marketing slogan. Automation can crush complexity and give you the one thing you can't get enough of ⎯ time.
Follow Linux principles of doing one thing, and one thing well. Keep roles and playbooks focused on a specific purpose. Multiple simple ones are better than having a huge single playbook full of conditionals and "programming" that Ansible is not well suited for.
We strive to reduce complexity in how we've designed Ansible and encourage you to do the same. Strive for simplification in what you automate.
If the implementation is hard to explain, it's a bad idea.
This aphorism, like "readability counts", is also taken directly from "The Zen of Python" because you cannot improve upon perfection.
In his essay on Literate Programming, Charles Knuth wrote, "Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do." So it goes that if you cannot explain or document your implementation easily, then it's a bad idea that needs to be rethought or scrapped. If it is hard to explain, what chance do others have of understanding it, using it and debugging it? Kernighan's Law says "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it."
Ansible is designed for how real people think and work. Recall earlier when I said Ansible Playbooks are human readable automation with no special coding skills needed. Take advantage of that. Then, if you are having trouble explaining what you are trying to do, pause and re-consider your implementation and the process you are trying to automate. How can I make it easier to explain? Can my process be improved or streamlined? How can I simplify and clarify? Can I break it down into smaller more focused parts and iterate over this?
This will help you identify a bad idea sooner and avoid the types of friction that will slow down you and your organization over time.
Every shell command and UI interaction is an opportunity to automate.
This aphorism comes from my personal experience talking about Ansible and automation for many years. Sometimes I am asked what they should automate. Other times, I am challenged that an automation tool like Ansible is unnecessary or does not apply to what they are doing. No matter if we were talking about RHEL, Windows, networking infrastructure, security, edge devices, or cloud services, my response has essentially been the same over the years. I have repeated it so often, that I have jokingly formulated the point into my own theorem on automation. So call it "Appnel's Theorem on Automation" if you will.
If you are wondering what should be automated, look for anything anyone is typing into a Linux shell and clicking through in a user interface. Then ask yourself "is this something that can be automated?" Then ask "what is the value of automating this?" Most Ansible modules wrap command line tools or use the same APIs behind UIs.
Given a sufficient number of things to automate is identified, start with those that cause the most pain and those that you can get done quickly. Remember you want to create a virtuous cycle of releasing reliability, feedback and building trust across your organization. Showing progress and business value quickly will help do that.
Just because something works, doesn't mean it can't be improved. Friction should be eliminated whenever possible.
This first aphorism just so happens to be a quote from the movie Black Panther, and it elegantly expresses some important wisdom when it comes to Ansible automation.
Always iterate and adapt to real world feedback from your operations. Optimize readability. Continue to find ways to simplify and reduce friction in your organization and its processes. As changes are introduced into your environments and IT policies over time, they will create new friction and pain points. They will also create new opportunities to apply your automation practices to eliminate them.
Automation is a journey that never ends.
Heraclitus, a Greek philosopher, said "change is the only constant in life. Nothing endures but change."
Anyone who has been around the IT industry for any length of time knows there is constant change. This is why it is so vital to be agile and prepared to respond to ongoing change, innovation and business demands quickly and reliably.
Automation is not a destination. It is a practice. It is a culture, a mindset and an attitude. Automation is a continuous process of feedback and learning and adapting to change and improving upon what you did before.
Automation creates opportunities and we at Red Hat see opportunities for automation everywhere.
So the question I pose to you is: Where will your automation journey lead you?
Further Reading
If you want to dive more deeply into the application of the zen of Ansible and its origins, I recommend these resources.
The Ansible Community of Practice (CoP) has assembled a comprehensive repository of "good practices" for Ansible content development. The Ansible Lint tool has now been added to the Red Hat Ansible Automation Platform and codifies many of these practices in rules and profiles to help you quickly identify and enforce consistent application to your work.
If you are interested in understanding more about "The Zen of Python", I recommend starting with Al Sweigart's explanation of those aphorisms.