In the last few months, I have been working with a software called Ansible. Some of you, by now, may know it as the third-party software that is used to deploy Viya.
However, Ansible can do so much more than that, and I am willing to bet that any SAS Admin/Installer/Architect who spends more than a couple days using it will come to like it as much as I do.
But the topic of this post is "Desired State" and that is the concept I want to illustrate. Ansible will simply help me in doing so.
It's 1995. Your friend phones you and says: "Come over check out my new house. Get on I-40 East. Get out at exit 287. At the light, turn right, then at the other light turn left. Then the first left, and you'll see my new house".
That's all well and good, but what if you took the wrong exit without noticing? You might end up at the wrong house. Or what if you came from a different direction? Was I-40 East still right?
Instead of telling you where he lived, your friend was giving you instructions on how to get there.
Fast forward to today. Your friend can now simply say "put [[35°49'46.7"N 78°45'53.6"W]] in your GPS, and let it take you to my place". That is all it takes. It does not matter where you start from. It does not matter if you make a mistake along the way.
Now that's progress! (oh, and if you've ever visited the SAS headquarters in Cary, then you may have stayed in that location. And no, it does not belong to me).
So, desired state is simply the concept of describing where we want to be, not how to get somewhere. Instead, you leave the tedious task of "getting you there" to something else. And if you are already there, then that something will not need to do anything.
Still with me? Let's use a computing example.
If you need to put something on a computer, it's not uncommon to create a folder. You may run commands like:
While this is completely acceptable, this command is actively changing something. If you were to run it again, it would fail:
[sasdemo@pdcesx03092 ~]$ mkdir ~/data mkdir: cannot create directory ‘/home/sasdemo/data’: File exists [sasdemo@pdcesx03092 ~]$
Yes, I know it does, but do you really have to give a failure for that?
If I wanted to do the same in Ansible, I would use the module of Ansible called "file", and execute this adhoc command:
ansible localhost -m file -a "path=~/data state=directory mode=0750"
As you can see here, I don't tell Ansible what I want it to do. I tell Ansible what I need to have. So when I run this for the first time, I get:
As you can see, "changed" is true, because Ansible had to change something to get me where I should be. But the result is a Success!
So if I run my task again, I obtain:
Once again, a resounding Success, but this time, changed=false: everything was OK, Ansible did not have to modify anything.
Now, can anyone guess how I get rid of that folder? I certainly won't tell Ansible how to do its job, I'll just declare that this folder should not exist. Something as simple as:
Another word for "desired state" is the word declarative. As opposed to "imperative".
Let me take an example: In the comic below, we make an imperative statement:
If we wanted to translate that into a Declarative statement, we would say something like "sudo there should be sandwich in my right hand". What it takes and how you get it done does not matter to me. You might decide to not make a sandwich, but buy it instead. I don't really care. I don't have the time or inclination to micro-manage you.
Ansible is not the only software out there that uses the "Declarative" approach. Many of Ansible's alternatives (Chef, Puppet, Salt) also have these concepts. And other technologies such as AWS CloudFormation are also declarative.
Idempotency essentially describes something that can be re-executed 1 or more times and will always give the same result.
For example, in an elevator, if you press the button for the 6th floor, it doesn't matter it you press it once or multiple times, the result is the same: you will stop at that floor. (credit to Wikipedia for the nice example).
Here is one more Ansible command. It uses the "lineinfile" module, rather than the "file" module:
ansible localhost -m lineinfile -a 'dest=/etc/ssh/sshd_config \ regexp="^MaxStartups" \ line="MaxStartups 1000" \ state=present'
As you can see, the second time I run this idempotent task, it does not need to do anything anymore. So, I could run this task every minute of every day, to make sure that if someone manually changed that value, my new best friend Ansible would immediately set it back to what it is supposed to be.
Old habits are hard to break. Many people who start with Ansible make extensive use of the "shell" module, which allows them to run any arbitrary command they want. My word of advice here is to always try to figure out how to use the right module instead, and only use "shell" as a last resort.
Take a look at this ad-hoc command:
ansible localhost -m shell -a "mkdir ~/data"
Can you spot the issue here?
Well, the first time you run this, you'll get a yellow changed status. But every time after that, you'll get a red error, because ... the folder already exists. This is not how you are supposed to do things.
Ansible has this particularity that it only checks and/or change state when you actively execute either a task or a playbook. Other Configuration Management software (I'm looking at you, Puppet), are designed in a way that this desired state is checked constantly, or at least very regularly.
While working on a project with a customer in New Zealand, I had asked for a particular folder to be created. After the folder was created, I noticed the permissions were wrong, and decided to correct them myself. Only to have my deployment later fail, because of wrong permissions. I mumbled something about "I'm certain I had corrected those permissions! Why are they wrong again?" to myself. I was thankfully overheard by one of the IT guys, who infomed me that I was essentially "fighting with puppet". No, it's not a kiwi insult. They had had the folder created through Puppet, and it was now undoing my manual changes. As soon as we told puppet what the permissions were supposed to be, things became a lot smoother.
Anyone who has deployed software knows that there are often a number of pre-requisites needed for the software to function. And often, these are performed once (manually), validated once (manually), before the software is then installed. However, if not properly managed, these pre-requisites can be the Achille's heel of the environment. I have seen many cases where major downtime was due to the un-doing of a particular pre-requisite. (such as removing ssh keys, changing folder permissions, etc...).
If one was to take the time to declare these pre-requisites in their Configuration Management tool of choice, one is then able to very quickly verify and fix all these pre-requisites.
Stay tuned for more examples of how this applies.