Search code examples
ansibleansible-2.xansible-inventory

Run the ansible task only once on localhost


I have below pseudo code to implement in ansible.

changed = true

if (changed)
{
   print("The first block executes")
}
else
{
  print("The second block executes.")
  changed = false
}

Now I need to convert above logic into ansible playbook , so that when I run the playbook first time , it prints the first block and all subsequent calls must print second block. I tried below but it didn't worked.

hosts: localhost
become: true
vars:
  changed: "true"
tasks:
  - name: First block
    debug:
      msg: "The first block is printed"
    when: changed == "true"
  - name: Second block
    debug:
      msg: "The second block is printed"
  - set_fact:
      changed: "false"

Can someone guide me if this use case can be implemented in ansible? The main ask is that can a playbook be designed such that it changes its behaviour after the first run. If I run the playbook first time it should print the first block but in all subsequent execution of that playbook it should only execute second block message only.


Solution

  • Remove the quotes around the variable.

    vars: 
      changed: true
    tasks:
    - name: First block
      debug:
        msg: "The first block is printed when changed is true"
      when: changed
    
    - name: Second block
      debug:
        msg: "The second block is printed when change is false"
      when: not changed
    

    Ansible is based on python and is the language is by itself 'truthy'.
    This should work as expected.

    Also note, you try to set changed to false, when it already is false. So you don't need to change that.

    -- edit --

    So, you told me:

    I add a device, then I check w lsblk whether that device is added.
    If it is added, Ansible fails on the second run.

    Again, Ansible is desired state. You shouldn't use lsblk commands, but rather use official modules.

    If you actually want to execute a shell command, and then run second command based on the output of the first command:

    - name: check lsblk
      shell: lsblk
      changed_when: false
    
    - name: only run this when device is not present
      shell: echo
      when: "'/my/device' not in lsblk.stdout"