e_scape
e_scape

Reputation: 99

Executing task only on the first run on each host

I'm new to ansible and I would like to run some tasks only once. Not once per every run but only once and then never. In puppet I used file placeholders for that, similar to ansible "creates".

What is the best practice for my use case?

If I should use the "creates" method, which folder should be safe to use?

For example I would like to install letsencrypt on host where the first step is to update snap. I don't want to refresh snap every run so I would like to run it only before letsencrypt install.

- name: Update snap
      command: snap install core && snap refresh core
      args:
        creates: /usr/local/ansible/placeholders/.update-snap
      become: true

Upvotes: 1

Views: 234

Answers (1)

zigarn
zigarn

Reputation: 11595

Most of the ansible modules are made to be idempotent, which means that they will perform action only when needed.

shell, script and command are the exception as ansible cannot know if action needs to be performed, and that's why there is the creates parameter to add idempotency.

That's why before writing a shell task you should check if there is not already an ansible module that could perform your task. There are almost 3000 base modules and with new versions of ansible you can get new community-provided modules through collections in Ansible Galaxy.

In your specific case, the snap module (https://docs.ansible.com/ansible/2.10/collections/community/general/snap_module.html) may be enough:

- name: Update snap
  snap:
    name: core
  become: true

It will install the core snap if it's not already installed, and do nothing otherwise.

If it's not enough, you can implement yourself idempotency by creating a task querying snap to check the presence of core with it's version (add a changed_when: False as it's a task not doing any changes) and then launching the install/update depending on the query result (with a when condition).

If there is no way to do that, then you can fallback to using the creates. If the command executed already creates a specific file that presence can be used to know if it was already executed, better to reference this one. Else you need to create your own marker file in the shell. As it's a last option solution, there is no convention of where this marker file should be, so up to you to create your own (the one you propose looks good, even if the file name could be more specific and include the snap name in case you should use the same trick for other snaps).

Upvotes: 2

Related Questions