I am trying to configure an Ansible task that will check for the existence of a specific cert within the Java cacerts keystore file, and if it does not exist, install it.
- name: copy cert to home
copy:
src: my_cert_file.crt
dest: /home/ec2-user/my_cert_file.crt
owner: root
group: root
mode: 0644
- name: check for domain SSL cert
shell: /usr/java/latest/bin/keytool -keystore /usr/java/latest/jre/lib/security/cacerts -storepass changeit -alias trusted_cert -list
register: trusted_cert
- name: install SSL cert into cacerts
shell: /usr/java/latest/bin/keytool -import -keystore /usr/java/latest/jre/lib/security/cacerts -storepass changeit -file /home/ec2-user/my_cert_file.crt -noprompt -alias trusted_cert
when: trusted_cert.stdout.find('trustedCertEntry') == 1
The above command, /usr/java/latest/bin/keytool -keystore /usr/java/latest/jre/lib/security/cacerts -storepass changeit -alias trusted_cert -list
, returns the following when the cert doesn't exist:
keytool error: java.lang.Exception: Alias <trusted_cert> does not exist
This causes the task to return FAILED!
, and causes the remaining tasks for the host to be skipped. When this task fails, however, I'd like the next step to install the cert. It already works correctly the other way — when the task succeeds, it does not attempt to install the cert, and it skips the install task.
I don't know enough about Ansible to say this definitively, but my assumption here is that when Java keytool is run and encounters the exception, it exits with status 1. Ansible sees the command exit status 1 and interprets this as a failure, and then reports the task as failed. The documentation on Ansible's error handling is good but it doesn't really talk about what's going on under the hood. So, is my assumption correct about how Ansible interprets the exit code 1, and I just need to ignore_errors: yes
while register
ing the output of name: check for domain SSL cert
?
I just want to clarify, I know how to solve the problem — my question isn't how to fix my Ansible tasks and make them work, but is to understand why my task is failing.
Best Answer
Anything non-zero exit status for the command is counted as a failure.
You can ignore all errors on the task:
or it's likely you could use
failed_when
to set conditions (I haven't tested this exact condition set, but you get the idea...) that ensure it fails if an unexpected failure is encountered, but continues if this expected one is seen: