I want to introduce you to one of my more recent open source projects. "PSAnsible.Playbook". What is it? It is basically nothing more than a wrapper around the "ansible-plabyook" excecutable. Instead of that excecutable you can use Powershell to start your playbooks and you will get results back in the way we all know and love it from powershell native tools/frameworks.
Let me demonstrate.
Setting up a small test enviornment
Setting up the module
If you want to follow along here you can follow the instructions on my docs page on Github: Docs on how to set up the module
The TLDR Version of that docs page is:
install ansible (either linux or mac, or WSL on Windows)
make sure powershell core is installed
install the module
Configure the ansible.cfg for ansible to output json
Setting up a dummy ansible environment
In order to make some quick tests on ansible I usually use a small dummy environment that looks like following.
Inventory
I set up an inventory at ”/etc/ansible/hosts" with the following content:
win:
hosts:
waap:
ansible_host: localhost
woop:
ansible_host: localhost
weep:
ansible_host: localhost
wuup:
ansible_host: localhost
In this inventory you will find that I define one group called "win". This group has 4 different hosts. Since I do not have a lab environment handy with 4 machines at all times I use "ansible_host: localhost" to make ansible think I have 4 host, where ansible actually will point all actions to localhost aka running it on itself. This is just a quick way to "test on multiple hosts" without having multiple hosts.
Playbook
Then comes the fun part. Writing your playbook.
this is what ansible is all about and almost always what I test in such a dummy environment. I would write a playbook to test out the syntax of ansible conditionals for example or whatever. For this example here a small playbook with an "echo” will be enough.
I continue to create my playbook as "/etc/ansible/ps.yml" and I fill it up with the following content:
---
- name: PSTest
hosts: win
connection: local
gather_facts: no
tasks:
- name: This is a debug message
debug:
msg: I am a debug message
Very simple, just a debug message.
Using ansible-playbook
Now normally what you would do is you would call your playbook like this:
ansible-playbook /etc/ansible/ps.yml -i /etc/ansible/hosts
this would then result in the following output:
PLAY [PSTest] ****************************************************************************************************************************************************************************************************************
TASK [This is a debug message] ***********************************************************************************************************************************************************************************************
ok: [waap] => {
"msg": "I am a debug message"
}
ok: [woop] => {
"msg": "I am a debug message"
}
ok: [weep] => {
"msg": "I am a debug message"
}
ok: [wuup] => {
"msg": "I am a debug message"
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************
waap : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
weep : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
woop : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
wuup : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Now this output is nice right? You see everything that happened and you also get a Play Recap at the end there. What more do you want?
Well.. Imagine how this would look like at scale. We can scale in two directions here. There can first of all be a lot more tasks in a playbook. And secondly you can target an inventory with way more hosts. Also what you get here may be nice to look at, but this is where the party ends. You have no way to programmatically continue your process and for example display the data you gathered during your playbook run, or validate that you have achieved a certain result in your run.
*** Now here PSAnsible.Playbook comes in to play. (pun fully intended). ***
Using PSAnsible.Playbook
Since you have prepared your enviornment and loaded the module in powershell you can run the following command:
$result = invoke-PSAnsiblePlaybook -Playbook /etc/ansible/ps.yml -i /etc/ansible/hosts
This will return an object in $result with all the information you need on the ansible playbook run. If you look at $result you will on the root level find all information on what has been excecuted:
~> $result
Playbook Param ExcecutionString RunResult
-------- ----- ---------------- ---------
/etc/ansible/ps.yml {-i} ansible-playbook /etc/ansible/ps.yml -i /etc/ansible/hosts PSAnsiblePlaybookRunResult
You see which playbook was excecuted, which parameters you have passed to the "ansible-playbook" excecutable. You can also see the exact line used to execute the playbook (ExcecutionString). This enables you to debug. If you encounter errors it is transparent what exactly ran.
And the most exciting part:
In the "RunResult" Property of the object you will find all details about your run in a structured format.
Let's have a look:
~> $result.RunResult.RunResult
hostname summary tasks
-------- ------- -----
waap @{changed=0; failures=0; ignored=0; ok=1; rescued=0; skipped=0; unreachable=0} {@{TaskName=This is a debug message; TaskDetails=}}
weep @{changed=0; failures=0; ignored=0; ok=1; rescued=0; skipped=0; unreachable=0} {@{TaskName=This is a debug message; TaskDetails=}}
woop @{changed=0; failures=0; ignored=0; ok=1; rescued=0; skipped=0; unreachable=0} {@{TaskName=This is a debug message; TaskDetails=}}
wuup @{changed=0; failures=0; ignored=0; ok=1; rescued=0; skipped=0; unreachable=0} {@{TaskName=This is a debug message; TaskDetails=}}
As you can see here you get an array. One instance per host, where all tasks are listed in the tasks property. And you have your summary where you can check each property (Changed, Failures etc.) as you like.
This in turn enables things like sorting on hosts where all tasks where no failures occured:
~> $result.RunResult.RunResult | ?{$_.summary.failures -eq 0}
hostname summary tasks
-------- ------- -----
waap @{changed=0; failures=0; ignored=0; ok=1; rescued=0; skipped=0; unreachable=0} {@{TaskName=This is a debug message; TaskDetails=}}
weep @{changed=0; failures=0; ignored=0; ok=1; rescued=0; skipped=0; unreachable=0} {@{TaskName=This is a debug message; TaskDetails=}}
woop @{changed=0; failures=0; ignored=0; ok=1; rescued=0; skipped=0; unreachable=0} {@{TaskName=This is a debug message; TaskDetails=}}
wuup @{changed=0; failures=0; ignored=0; ok=1; rescued=0; skipped=0; unreachable=0} {@{TaskName=This is a debug message; TaskDetails=}}
You see where I'm going with this. You have Ansible playbook run results in powershell which you can further on use however you like.
Cool usecases that come to mind immediatly:
Display Results of Ansible Playbook Runs in a nice way (PSHTML??)
Test your Ansible playbooks with Pester!
Possibilites are limited by the things you do with Powershell. Or any language you choose to pass your results to.
Closing
This is it folks. That's my most recent project. It was not to big of a deal, but I'm certainly going to use this. I like the possibilities this opens up for People who are open to use Powershell on linux. This Module of course also work if you target linux machines with ansible, so maybe if a linux engineer could step over the shadow and use Powershell on linux they could even profit from this ;)
Hit me up on twitter @_bateskevin if you have any questions about it.
But yeah, that's that.
Comments