-2

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.

isilia
  • 379
  • 1
  • 11
  • 1
    [`But the above logic is not working for me` does not help to answer your question](https://idownvotedbecau.se/itsnotworking/). Please [edit] your question and make it a [mre]. Moreover, I suggest you ground your question to a real life example rather than some pseudo code as the above looks like an ansible anti-pattern and an [x/y problem](https://xyproblem.info) – Zeitounator Aug 28 '23 at 13:03

1 Answers1

2

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"
Kevin C
  • 4,851
  • 8
  • 30
  • 64
  • But this will always run the first block. The ask is to run the first block only once on localhost and if I run the playbook again it should print second block only – isilia Aug 28 '23 at 13:18
  • That’s not how ansible would work. Can you provide your actual use case? – Kevin C Aug 28 '23 at 13:33
  • My use case is - I was trying to add some devices on the server. It tries to find the newly added devices using lsblk command. Now if the playbook run once it will work fine but if you run the playbook second time , it will fail as the command used to find newly added devices are already added. – isilia Aug 28 '23 at 13:35
  • Thats why I created a sample playbook to test the same scenario , can ansible 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. – isilia Aug 28 '23 at 13:36
  • I'll update my answer. – Kevin C Aug 28 '23 at 14:34
  • 2
    @isilia This is why I advised you above to ground your question to a real world case. You are taking this the wrong way. You are approx. asking how to set a fact with cache between runs where you exact problem is to list devices on an ansible managed node. This is the exact definition of an [x/y problem](https://xyproblem.info). The list of devices is available out of the box in the node gathered facts: look for `{{ ansible_devices }}`. You can get their names only with e.g. `{{ ansible_devices.keys() }}` and you could write a condition like `when: "'MyDevice' not in ansible_devices.keys()"` – Zeitounator Aug 28 '23 at 16:03