Reputation: 99
I need to write an ansible module using bash (since I do not know python). This is the shell module I used in my playbook that worked:
- name: Finding out what web server it uses
shell: "lsof -i :80 | grep LISTEN | cut -d ' ' -f 1"
register: result
- name: output the result of what web server it uses
debug: msg="{{ result.stdout_lines|first }}"
And this is the wbsrv.sh
bash script located where ansible.cfg
wants it.
#!/bin/bash
lsof -i :80 | grep LISTEN | cut -d ' ' -f 1
if [ $? == 0 ]; then
printf '{"changed": true, "rc": 0}'
else
printf '{"failed": true, "msg": "Something went wrong", "rc": 1}'
fi
And so I changed my playbook to this
- name: Finding out what web server it uses
wbsrv:
register: result
- name: output the result of what web server it uses
debug: msg="{{ result.stdout_lines|first }}"
When I run the playbook the error happens at "TASK [output the result of what web server it uses]":
fatal: [vm2]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'stdout_lines'\n\nThe error appears to have been in '/home/ansible/wbsrvtest.yml': line 19, column 6, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n register: result\n - name: output the result of what web server it uses\n ^ here\n\nexception type: <class 'ansible.errors.AnsibleUndefinedVariable'>\nexception: 'dict object' has no attribute 'stdout_lines'"}
I tried removing the conditionals in the bash script. I tried putting echo
instead of printf
. I also tried setting RESULT
variable to equal the line of bash code in the script and then echoing that in the if statement but all of that returned a similar error.
Upvotes: 1
Views: 424
Reputation: 484
So it looks like you have a couple of things going on here. Calling the bash script doesn't need to be as complicated as creating a new module. If you want to make a module like that, you usually have to write it in python code.
https://docs.ansible.com/ansible/2.3/dev_guide/developing_modules_general.html
But it doesn't need to be that hard, you can just use ansibles pre-written modules to run your bash script for you. Create your bash script, and if you aren't running it against localhost only, use the copy module to place it on your remote host, and then just call it with the shell module, and that will give you the output that you are looking for. Also, I don't know if this was just a paste error, but your indentation in your example doesn't look right. Ansible is SUPER picky about indentation, so the module name isn't indented further than the 'name' designator. So you could try something like this:
- name: Place shell script
copy:
src: < source file path >/wbsrv.sh
dest: < desired file location >/wbsrv.sh
owner: < desired owner >
group: < desired group >
mode: < desired permissions >
- name: Finding out what web server it uses
shell: < desired file location >/wbsrv.sh
register: result
- name: output the result of what web server it uses
debug: msg="{{ result.stdout }}"
And if you don't want to leave artifacts just run another shell command module deleting the shell script that you placed. Also, if you are going to have your shell script only output a single line, you don't need to do the stdout_lines and cut it down. And if you run the playbook with the verbose flag, you can actually see the output of the shell command right in the output removing the need for the debug statement and the register (but it won't be as pretty).
Upvotes: 1