0

I have a shell script, which triggers an ansible-playbook command say ansible-playbook install.yml.
This works perfectly fine.

Now inside the shell script, based on whether the Ansible command was successful or failure, I need to do something.
Is there a way to capture the exit code of an Ansible command so that I can use it for further steps inside the shell script?

Any alternate approaches would also be really helpful.

β.εηοιτ.βε
  • 33,893
  • 13
  • 69
  • 83
Vinay
  • 59
  • 1
  • 8
  • 2
    How about checking for `$?` after the ansible command? – seshadri_c Nov 24 '21 at 06:58
  • Thank you for the quick support. Tried using the above approach. But for some weird reason it always returns zero, even if the ansible command failed. – Vinay Nov 24 '21 at 07:21
  • 3
    Then you are not looking for Ansible command rc but for the number of failed hosts present in the output. You will have to parse it yourself. If you had already tried something, edit your question and add this info there so that people don't waste their time proposing solutions that are already ruled out. – Zeitounator Nov 24 '21 at 07:31
  • There are indeed tons of question behind this. What are you really trying to achieve here, in a broader scope? With the limited scope we can only say: mind that a playbook can target multiple hosts, how would you deal with this only based on the exit code of the `ansible-plabook` command? Why don't you go the other way around and have a your playbook do "what the shell does"? This would make it easier to get the `rc` of specific Ansible tasks. – β.εηοιτ.βε Nov 24 '21 at 09:32
  • [Why is testing “$?” to see if a command succeeded or not, an anti-pattern?](https://stackoverflow.com/questions/36313216/why-is-testing-to-see-if-a-command-succeeded-or-not-an-anti-pattern) – tripleee Nov 24 '21 at 10:57

1 Answers1

0

Q: "The command ansible-playbook always returns zero even if the ansible tasks failed."

A: The return code of ansible-playbook does not report the status of the hosts. For example, create the inventory and playbook

shell> cat project/inventory/hosts 
host1
host2
host3

shell> cat project/test.yml
- hosts: host1,host2,host3
  gather_facts: false
  tasks:
    - fail:
      when: '[true, false] | random'

The returned code is 0 despite the fact that one host failed

shell> ansible-playbook -i project/inventory/hosts project/test.yml

PLAY [host1,host2,host3] **************************************************

TASK [fail] ***************************************************************
fatal: [host1]: FAILED! => changed=false 
  msg: Failed as requested from task
skipping: [host2]
skipping: [host3]

PLAY RECAP ****************************************************************
host1 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0   
host2 : ok=0 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0   
host3 : ok=0 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

shell> echo $?
0

Use ansible-runner if you want to analyze the status of a playbook. For example

shell> ansible-runner run project -p test.yml -i 001

PLAY [host1,host2,host3] *******************************************************

TASK [fail] ********************************************************************
skipping: [host2]
fatal: [host1]: FAILED! => {"changed": false, "msg": "Failed as requested from task"}
skipping: [host3]

PLAY RECAP *********************************************************************
host1: ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0   
host2: ok=0 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0   
host3: ok=0 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

shell> echo $?
2

creates the directory artifacts/001

shell> tree project/artifacts/001/
project/artifacts/001/
├── command
├── fact_cache
├── job_events
│   ├── 10-0e67d8d4-0e4a-4997-b3ab-3d0189534132.json
│   ├── 10-4dfea3b2-baf6-46a8-b4ab-e22af5a8d55b.json
│   ├── 1-6afdcfe5-734e-4c4d-b00a-aacd6367c758.json
│   ├── 1-832947cc-0af6-47bc-a15c-fb71b565a9d3.json
│   ├── 2-9d4346a9-cd36-4f14-9c9f-000000000008.json
│   ├── 2-9d4346a9-cd36-78bf-89f1-000000000008.json
│   ├── 3-9d4346a9-cd36-4f14-9c9f-00000000000a.json
│   ├── 3-9d4346a9-cd36-78bf-89f1-00000000000a.json
│   ├── 4-0421a1df-52c1-4c8a-89af-25dff1146b5d.json
│   ├── 4-dad41025-1974-4cd0-829d-2cab9a7ac541.json
│   ├── 5-36628db6-cf46-4ccc-bb67-e510bfa03d85.json
│   ├── 5-61adde59-937d-40b6-8a2d-72c2bdc69a68.json
│   ├── 6-1aad67ba-7cc0-438b-9926-6861359ecedd.json
│   ├── 6-9b9272e1-f332-45eb-836b-453595e5af4a.json
│   ├── 7-41959751-8bd8-4da2-8053-5f61151dc803.json
│   ├── 7-ed0c5919-ea3c-4d41-8690-7877c9639dcf.json
│   ├── 8-93f5146b-1164-45d6-ad3d-38c356cab19c.json
│   ├── 8-cc90147f-eca0-46ed-b3f9-fd2938dab5ce.json
│   ├── 9-274c9f8f-384e-426d-8832-4625cd75f945.json
│   └── 9-287f4ffa-4073-45f4-9bc5-e91837b4abbb.json
├── rc
├── status
├── stderr
└── stdout

2 directories, 25 files

The status is failed and the return code is 2 if any of the hosts failed

shell> cat project/artifacts/001/status 
failed
shell> cat project/artifacts/001/rc 
2

See other artifacts and examples of how to use them in scripts.

Vladimir Botka
  • 58,131
  • 4
  • 32
  • 63