Home > Software engineering >  Ansible showing task changed but the task has condition (creates: ) and does not actually execute
Ansible showing task changed but the task has condition (creates: ) and does not actually execute

Time:01-04

My ansible-playbook is running some long running task with async tag and also utilizes "creates:" condition, so it is run only once on the server. When I was writing the playbook yesterday, I am pretty sure, the task was skipped when the log set in "creates:" tag existed.

It shows changed now though, everytime I run it.

I am confused as I do not think I did change anything and I'd like to set up my registered varaible correctly as unchanged, when the condition is true.

Output of ansible-play (debug section shows the task is changed: true):

    TASK [singleserver : Install Assure1 SingleServer role] *********************************************************************************************************************************
changed: [crassure1]

TASK [singleserver : Debug] *************************************************************************************************************************************************************
ok: [crassure1] => {
    "msg": {
        "ansible_job_id": "637594935242.28556",
        "changed": true,
        "failed": false,
        "finished": 0,
        "results_file": "/root/.ansible_async/637594935242.28556",
        "started": 1
    }
}

But if I check the actual results file on the target maschine, it correctly resolved condition and did not actually execute the shell script, so the task should be unchanged (shows message the task is skipped as the log exists):

[root@crassure1 assure1]# cat "/root/.ansible_async/637594935242.28556"
{"invocation": {"module_args": {"warn": true, "executable": null, "_uses_shell": true, "strip_empty_ends": true, "_raw_params": "/opt/install/install_command.sh", "removes": null, "argv": null, "creates": "/opt/assure1/logs/SetupWizard.log", "chdir": null, "stdin_add_newline": true, "stdin": null}}, "cmd": "/opt/install/install_command.sh", "changed": false, "rc": 0, "stdout": "skipped, since /opt/assure1/logs/SetupWizard.log exists"}[root@crassure1 assure1]# Connection reset by 172.24.36.123 port 22

My playbook section looks like this:

- name: Install Assure1 SingleServer role
  shell:
    #cmd: "/opt/assure1/bin/SetupWizard -a --Depot /opt/install/:a1-local --First --WebFQDN crassure1.tspdata.local --Roles All"
    cmd: "/opt/install/install_command.sh"
  async: 7200
  poll: 0
  register: Assure1InstallWait
  args:
    creates: /opt/assure1/logs/SetupWizard.log

- name: Debug
  debug:
    msg: "{{ Assure1InstallWait }}"

- name: Check on Installation status every 15 minutes
  async_status:
    jid: "{{ Assure1InstallWait.ansible_job_id }}"
  register: job_result
  until: job_result.finished
  retries: 30
  delay: 900
  when: Assure1InstallWait is changed

Is there something I am missing, or is that some kind of a bug?

I am limited by Ansible version available in configured trusted repo, so I am using ansible 2.9.25

CodePudding user response:

Q: "The module shell shows changed every time I run it"

A: In async mode the task can't be skipped immediately. First, the module shell must find out whether the file /opt/assure1/logs/SetupWizard.log exists at the remote host or not. Then, if the file exists the module will decide to skip the execution of the command. But, you run the task asynchronously. In this case, Ansible starts the module and returns without waiting for the module to complete. That's what the registered variable Assure1InstallWait says. The task started but didn't finish yet.

    "msg": {
        "ansible_job_id": "637594935242.28556",
        "changed": true,
        "failed": false,
        "finished": 0,
        "results_file": "/root/.ansible_async/637594935242.28556",
        "started": 1
    }

The decision to set such a task changed is correct, I think because the execution on the remote host is going on.

Print the registered result of the module async. You'll see, that the command was skipped because the file exists (you've printed the async file at the remote instead). Here the attribute changed is set false because now we know the command didn't execute

  job_result:
    ...
    attempts: 1
    changed: false
    failed: false
    finished: 1
    msg: Did not run command since '/tmp/SetupWizard.log' exists
    rc: 0
    ...
  •  Tags:  
  • Related