Ansible : How to run playbooks as a shell script


Ansible is a powerful tool for automation, its syntax checking, verbose and dry run mode features make it a reliable and safe tool. It is particularly popular in IT infrastructure automation, such as application deployment or full fledged infrastructure plus app deployment. As an integral part of DevOps tool-set, it falls into the category of Chef, Puppet, Salt or CFEngine for the critical role it plays in IT infrastructure, Application Deployment, Configuration Management and Continuous Delivery.

In this short blog, I am writing about a little known or less popular usage of Ansible – executing it like a shell script. In a Unix-like operating system, any text file with its content starting with a #! aka Shebang, is executed by passing the text file as an argument to the characters following the Shebang. For instance, a text file /tmp/myscript.sh with its content starting with the characters #!/bin/bash is run by the program loader as /bin/bash /tmp/myscript. Following the same logic, we can execute any ansible playbook by simply starting the content of the playbook file with a path to the ansible executable. 

Thus for me to execute my playbooks just like a script, the first thing I need to know is the path to my Ansible executable –

$ which ansible
/usr/local/bin/ansible

And have a playbook – in this case, I will use two playbook – one which adds a user and the second one which deletes the same user as examples.
Notice that I am naming the playbook just like a shell script and made it executable –

$ cat add-user.sh 
#!/usr/local/bin/ansible-playbook
---
- hosts: localhost
  tasks:
  - name: Add user
    user: name={{ username }} comment={{ comment }} state=present shell={{ shell }}
    become: yes

When I execute this script, I will pass the parameters needed to add a user as ansible Extra variables. Now let us run the script in dry run mode first –

$ id john
id: ‘john’: no such user

$ ./add-user.sh -e "username=john comment='John Doe' shell=/bin/bash" -v --check
Using /etc/ansible/ansible.cfg as config file

PLAY [localhost] ************************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************
ok: [localhost]

TASK [Add user] *************************************************************************************************************************************
changed: [localhost] => {"changed": true}

PLAY RECAP ******************************************************************************************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0

Everything looks good, so let us execute it –

$ ./add-user.sh -e "username=john comment='John Doe' shell=/bin/bash" -v
Using /etc/ansible/ansible.cfg as config file

PLAY [localhost] ************************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************
ok: [localhost]

TASK [Add user] *************************************************************************************************************************************
changed: [localhost] => {"changed": true, "comment": "John Doe", "create_home": true, "group": 1002, "home": "/home/john", "name": "john", "shell": "/bin/bash", "state": "present", "stderr": "useradd: warning: the home directory already exists.\nNot copying any file from skel directory into it.\n", "stderr_lines": ["useradd: warning: the home directory already exists.", "Not copying any file from skel directory into it."], "system": false, "uid": 1002}

PLAY RECAP ******************************************************************************************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0

$ id john
uid=1002(john) gid=1002(john) groups=1002(john)

Deleting the user is similar, we just write an equivalent playbook and we pass only the username name as an extra var this time –

$ cat del-user.sh
#!/usr/local/bin/ansible-playbook
---
- hosts: localhost
tasks:
- name: Delete user
user: name={{ username }} state=absent
become: yes

$ ./del-user.sh -e username=john -v --check
Using /etc/ansible/ansible.cfg as config file

PLAY [localhost] ************************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************
ok: [localhost]

TASK [Delete user] **********************************************************************************************************************************
changed: [localhost] => {"changed": true}

PLAY RECAP ******************************************************************************************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0

$ ./del-user.sh -e username=john -v
Using /etc/ansible/ansible.cfg as config file

PLAY [localhost] ************************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************
ok: [localhost]

TASK [Delete user] **********************************************************************************************************************************
changed: [localhost] => {"changed": true, "force": false, "name": "john", "remove": false, "state": "absent"}

PLAY RECAP ******************************************************************************************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0

$ id john
id: ‘john’: no such user

You can find more on Ansible in the documentation section of the official site.