4

I use command module with creates on an ansible 2.9 role.

However, sometimes I need to ignore the creates arg and re-run the command multiple times.

Is there any way I can override the default behaviour and force the execution of the tasks?

trikelef
  • 518
  • 1
  • 7
  • 26

2 Answers2

6

One very basic solution. In your task:

- name: Do command optionally ignoring create option
  command:
    cmd: touch /tmp/toto.txt
    creates: "{{ ignore_creates | default(false) | bool | ternary('', '/tmp/toto.txt') | default(omit, true) }}"

Then you can launch your playbook with the the extra var -e ignore_creates=true to force the task to run even if the file exists. Removing the extra var in your command will turn the condition on again.

Zeitounator
  • 1,199
  • 5
  • 12
  • Thanks! However, since I have many tasks with different `creates` it would require great effort to change this. I was wondering for an option that would ignore all similar conditions. Otherwise a major rewrite is unavoidable. – trikelef Apr 09 '21 at 14:11
  • You could write a custom filter which would ease the rewrite (to something like `creates: "{{ 'my/file.txt' | skip_if_var_present }}"`). Meanwhile 1) I currently have no idea how to return `omit` from there (and not even if it is possible). 2) you will still have to rewrite all of your `creates`. An other track you might want to explore is to write a [custom module](https://docs.ansible.com/ansible/latest/dev_guide/developing_modules_general.html) with a corresponding [action plugin](https://docs.ansible.com/ansible/latest/dev_guide/developing_plugins.html#action-plugins) to call `command` – Zeitounator Apr 09 '21 at 14:26
  • 1
    If you are writing a custom module, don't wrap the command module. Run it directly from your module, such as with `ansible.module_utils.basic.AnsibleModule.run_command` Many examples of this in existing Ansible modules. – John Mahowald Apr 09 '21 at 15:35
2

Repeating expressions can be a practical sometimes, don't try too hard to comply to DRY. Although you can reuse an expression with variables.

- name: Testing creates parameter
  hosts: localhost
  vars:
    # Long expression for reuse in command tasks
    # Special value "omit" can be returned
    # from any expression, including ternary filter
    creates: "{{ ignore_creates | default(false) | bool | ternary(omit, creates_file) }}"

  tasks:
  - name: Do command optionally ignoring create option
    command:
      cmd: touch {{ creates_file }}
      creates: "{{ creates }}"
    vars:
      # Task level var to for use in the creates expression
      # Still a lot of typing, 
      # but perhaps you don't want to retype the filter
      ignore_creates: false
      creates_file: /tmp/ansiblecreatestest.txt

  - command:
      cmd: touch {{ creates_file }}
      creates: "{{ creates }}"
    vars:
      ignore_creates: true
      creates_file: /tmp/ansiblecreatestest.txt

Writing fancy logic into the playbook, wrapping more generic modules, will get tedious and repetitive whatever you do.

Instead, consider writing a custom module to run the commands. Write the logic for when the commands need to be re-run into the module.

John Mahowald
  • 32,050
  • 2
  • 19
  • 34