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 –
1 2 | $ 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 –
1 2 3 4 5 6 7 8 | $ 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 –
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | $ 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 –
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | $ . /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 –
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | $ 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.