Score:0

Make a skipped task show as "OK"

ru flag
jdm

I have some ansible tasks that are run in two parts. The first part sets a condition, and the second part uses when to conditionally execute. Pseudo-example:

- name: check if installed
  command: (...)
  register: is_installed

- name: run install script
  when: is_installed.stdout == "yes"
  command: (...)

The second task shows as "skipped". This is not really right, I did not forgo the installation, but confirmed that it was already done, so it should show as "OK". It should show "skipped" only if the given host doesn't need this step. I know this is just cosmetic, but I would still like to know if there is a way to get it to say "OK".

I tried setting changed_when to False. While this sets the result to OK, it still runs the command. Somebody asked for an ok_when setting, but it was declined and I'm not sure the developers understood the request.

U880D avatar
ca flag
From your description I understand that you like to install or configure "something" on the remote node(s). You like to confirm on the next run of the task that that is still the case. For me it sound like idempotent installing a package and to achieve this goal no `skipped` check of `ok_when` would be necessary.
ru flag
jdm
Right, but the installation is not via apt, pip and so on, so I can't use a specialized task. In the general case I have two shell commands, one tells me if an action is neccessary, and one takes the action. It seems like this would be one of the most basic things you can do in ansible.
U880D avatar
ca flag
Since no information is provided what the "something" might be, I can only guess some cases. Since Ansible is a configuration management tool with which one declare a state, tasks are usually organized to make sure that something is in a certain state. With this in mind an installer (script) could run twice and be idempotent. In almost all cases no check would be necessary before.
U880D avatar
ca flag
It might also be possible to have a check just in your shell command like for `needs-restarting -r || /usr/sbin/shutdown -r +1`, let the command run if necessary and providing feedback for the Ansible environment back via return codes, stderr, stdout.
Score:2
ng flag

I couldn't come up with general solution here. But if tasks actually installs something you could remove first part and add creates to second part to implement check.

- name: run install script
  creates: /path/to/installation
  command: (...)
ru flag
jdm
Yes, that seems to be the ideomatic solution. The alternative would be to write a custom module which knows itself how to check for "OK". It's weird that there is no simple way to define it in YAML.
U880D avatar
ca flag
Right, that's what the [`command` module parameter `creates`](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/command_module.html#parameter-creates) or [`shell` module parameter `creates`](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/shell_module.html#parameter-creates) are for. See also in example [ansible/modules/command.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/command.py), "_while the command itself is arbitrary and cannot be subject to the check mode semantics it adds C(creats)/C(removes) options as a workaround_".
Score:1
cn flag

when: evaluating to false results in a status skipped on that task. Printing something on skipped comes from the standard out callback plugin. For default based callbacks, this can be disabled globally with the display_skipped_hosts configuration item. See the docs: ansible-doc -t callback default

An elegant solution could be to wrap this thing in a real package manager, and install that. Several idempotent package manager modules exist for Ansible.

Or, the install script could be made safe to re-run, and returns with a zero code on success.


While I don't speak for the developers, they are cautious about adding features to core. And possibly they don't see a problem with a task reported as skipped, not every task of every play gets run.

when: controls if a task runs. changed_when: and failed_when: modify the status of a task after it runs, such as based off return code or standard out. Together these give control over if a task is a status of changed or failed, even for generic command tasks.

For more control over idempotency, use a less generic module. And if you still are offended by what is printed, consider a custom callback plugin.

Score:0
ad flag

How about modifying command that is executed in "check if installed" task to exit 0 when installation is needed and exit 1 when it is not and leveraging shell && to controll execution of chained commands.

You could also reverse the logic (check_script exit 0 means its already there, exit 1 means missing stuff, needs install) and use || to glue chained scripts together.

Then you can do single task in your playbook:

- name: install stuff where needed
  shell: <check_command> && <install_command>
  register: installtask
  changed_when: "<check_stdout_indicating_install_required>" in installtask.stdout

This task will always run but depending on exit status of check script, install part will or will not be executed on target host. changed_when can controll displaying "OK" or "Changed" as outcome of this task depending on actual installation taking place or not.

If there is at least one file added to the system as a result of <install_script> then 'creates: <file/path>' as in the other answer will take care of whole scenario.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.