ansibleundefinedadditionundefined-variable

ansible play fails with error - The task includes an option with an undefined variable


The below ansible code fails with the error: The task includes an option with an undefined variable. The error was: 'storage_size_gb' is undefined

- debug:
    msg: "{{ mongo_output_withoutvar.stdout }}"

- set_fact:
   storage_size_gb: "{{ mongo_output_withoutvar.stdout | int }}"
   min_free_space_rec: "{{ min_free_space_pass | int }}"
   combined_output: "{{ storage_size_gb + min_free_space_rec }} GB"

Output:

TASK [debug] *******************************************************************
ok: [ip-10-236-75-137.ec2.internal] => {
    "msg": "25"
}

TASK [set_fact] ****************************************************************
fatal: [remotehostl]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'storage_size_gb' is undefined\\n\\nThe error appears to be in '/runner/project/backupmongodb.yml': line 220, column 7, but may\\nbe elsewhere in the file depending on the exact syntax problem.\\n\\nThe offending line appears to be:\\n\\n\\n    - set_fact:\\n      ^ here\\n"}

I tried to run a sample testcase where i get the same error:

---
- hosts: localhost
  gather_facts: false

  vars:
    min_free_space_pass: "30"

  tasks:
    - set_fact:
        storage_size_gb: 40
        min_free_space_rec: "{{ min_free_space_pass | int }}"
        combined_output: "{{ storage_size_gb + min_free_space_rec }} GB"

    - debug:
        var: combined_output

Run: ansible-playbook sample.yml

Output:

PLAY [localhost] ************************************************************************************************************** 

TASK [set_fact] ***************************************************************************************************************

Wednesday 11 October 2023  02:41:29 -0500 (0:00:00.055)       0:00:00.055 *****

fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'storage_size_gb' is undefined\n\nThe error appears to be in '/home/wladmin/testset.yml': line 7, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n  tasks:\n    - set_fact:\n      ^ here\n"}

PLAY RECAP ********************************************************************************************************************

localhost                  : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

Can you please suggest how I can overcome this error?


Solution

  • The error comes from the fact you declare and use the same variable inside the same set_fact task as reported in @β.εηοιτ.βε comment. Meanwhile, there is absolutely no valid reason to use set_fact here. The following playbook should get you going:

    ---
    - hosts: localhost
      gather_facts: false
    
      vars:
        min_free_space_pass: 30
        storage_size_gb: 40
        combined_output: "{{ storage_size_gb | int + min_free_space_pass | int }} GB"
    
      tasks:
        - ansible.builtin.debug:
            var: combined_output
    

    Running the playbook gives:

    $ ansible-playbook test_playbook.yml
    
    PLAY [localhost] ***************************************************************
    
    TASK [debug] *******************************************************************
    ok: [localhost] => {
        "combined_output": "70 GB"
    }
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 
    

    To apply this to your real case (where I suspect you register a value from an other task) here is a pseudo example:

    ---
    - hosts: whatever_group
      gather_facts: false
    
      vars:
        min_free_space_pass: 30
        combined_output: "{{ mongo_output_withoutvar.stdout | int + min_free_space_pass | int }} GB"
    
      tasks:
        - name: Get info from mongo (dummy task to replace with real)
          ansible.builtin.command: echo 40
          register: mongo_output_withoutvar
          changed_when: false
    
        - name: Debug my var
          ansible.builtin.debug:
            var: combined_output
    

    This is also testable (targeting only localhost for the test). But note that this will work for whatever number of servers you target:

    $ ansible-playbook almost_real_playbook.yml
    
    PLAY [localhost] ***********************************************************************************************************************
    
    TASK [Get info from mongo (dummy task to replace with real)] **************************************************************************
    ok: [localhost]
    
    TASK [Debug my var] ********************************************************************************************************************
    ok: [localhost] => {
        "combined_output": "70 GB"
    }
    
    PLAY RECAP *****************************************************************************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0