FileNotFoundError: [Errno 2] No such file or directory : Ansible

12.3k Views Asked by At

I'm new to Ansible, here I created a module which takes CSV as an argument like below: But it keep throwing error that it's not able to find CSV_TEST.csv file. am I creating it the right way as a variable in the ansible module?

module.py

def main():
    field = dict(
        csv=dict(type='str', required=True)
    )

    result = dict(
        changed=False,
        response='')

    module = AnsibleModule(argument_spec=field)

    csvFile = module.params['csv']

    listFinal = list()
    final = list()

    if csvFile:
        with open(csvFile, "r", newline='', encoding='utf-8-sig') as csvImport:
            reader = csv.DictReader(csvImport)
            for row in reader:
                newDict = dict({
                    'name': row.get("Name"),
                    'address': row.get("Address")
                    'val': row.get("Val")
                })
                listFinal.append(newDict)


    if listFinal:
        for entry in listFinal:
            if entry.get("val") == "Incorrect":
                name = entry.get('name')
                add = entry.get('address')
                update = f'set add {add} of {name}'

                final.append(update)

        result['final'] = final

    module.exit_json(changed=False, meta=result)


if __name__ == '__main__':
    main()

Playbook.yml

---
- name: Test Variables with Ansible
  hosts: localhost
  vars:
    x: 30
    xName: "Sai"
  gather_facts: false
  become: false
  tasks:
    - name: Test Device Validation
      portDescription:
        csv: CSV_TEST.csv
      register: result

    - debug: var=result

The error is:

***
FileNotFoundError: [Errno 2] No such file or directory: 'CSV_TEST.csv'
fatal: [localhost]: FAILED! => {
    "changed": false,
    "module_stderr": "Shared connection to localhost closed.\r\n",
***

Can someone please suggest, what am I doing wrong here? CSV_TEST.csv is under the same tree structure (parent folder) like Playbook.yml

2

There are 2 best solutions below

3
On

I think that if you have a relative file path in Ansible, Ansible will look in the local directory first (that is whatever directory is output if you run ran ansible from) then it looks in some other locations (check out the role directory structure for info on that).

So in my mind your directory structure is like

WorkingDir
|- playbook.yml
|- Ansible
   |- CSV_TEST.csv

And I think you are running ansible like ansible-playbook playbook.yml from inside WorkingDir. It can't find CSV_TEST.csv because it's looking in WorkingDir.

If inside the python you have to put Ansible/CSV_TEST.csv then you also have to put Ansible/CSV_TEST.csv in your playbook. So

---
- name: Test Variables with Ansible
  hosts: localhost
  vars:
    x: 30
    xName: "Sai"
  gather_facts: false
  become: false
  tasks:
    - name: Test Device Validation
      portDescription:
        csv: Ansible/CSV_TEST.csv
      register: result

    - debug: var=result

If this doesn't help then can you write out the directory structure in a text format and show where everything is executed from and where python is running (what os.getcwd() outputs)?

1
On

Once I fix the problems I reported in my above comment, I don't see anything else wrong with your code. There might be logic problems (but I have no idea what is the exact expectation). For now, here is a proof run that it works as expected from what I can read in your module code. The paths below are all relative to the current working dir where I launched the playbook from.

The module stored in ./library/port_description.py

#!/usr/bin/python
from ansible.module_utils.basic import *
import csv

def main():
    field = dict(
        csv=dict(type='str', required=True)
    )

    result = dict(
        changed=False,
        response='')

    module = AnsibleModule(argument_spec=field)

    csvFile = module.params['csv']

    listFinal = list()
    final = list()

    if csvFile:
        with open(csvFile, "r", newline='', encoding='utf-8-sig') as csvImport:
            module.debug("csv openned")
            reader = csv.DictReader(csvImport)
            for row in reader:
                newDict = dict({
                    'name': row.get("Name"),
                    'address': row.get("Address"),
                    'val': row.get("Val")
                })
                listFinal.append(newDict)

    if listFinal:
        for entry in listFinal:
            if entry.get("val") == "Incorrect":
                name = entry.get('name')
                add = entry.get('address')
                update = f'set add {add} of {name}'

                final.append(update)

        result['final'] = final

    module.exit_json(changed=False, meta=result)


if __name__ == '__main__':
    main()

The csv file stored in ./CSV_TEST.csv (tried to create something aligned to expected names and python code...)

Name,Address,Val
toto,127.0.0.1,3
titi,192.168.0.1,Incorrect

The playbook stored in ./test.yml

---
- name: Use a custom module reading csv file
  hosts: localhost
  gather_facts: false

  tasks:
    - name: Use our module and register result
      port_description:
        csv: CSV_TEST.csv
      register: port_result

    - name: Show the result
      debug:
        var: port_result

And the result:

$ ansible-playbook test.yml 

PLAY [Use a custom module reading csv file] ********************************************************************************************************************************************************************************************

TASK [Use our module and register result] **********************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Show the result] *****************************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "port_result": {
        "changed": false,
        "failed": false,
        "meta": {
            "changed": false,
            "final": [
                "set add 192.168.0.1 of titi"
            ],
            "response": ""
        }
    }
}

PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Note that I can easilly reproduce your exact problem if I remove the given CSV file from its expected location:

$ mv CSV_TEST.csv CSV_TEST.csv.BAK
$ ansible-playbook test.yml 

PLAY [Use a custom module reading csv file] ********************************************************************************************************************************************************************************************

TASK [Use our module and register result] **********************************************************************************************************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: FileNotFoundError: [Errno 2] No such file or directory: 'CSV_TEST.csv'
fatal: [localhost]: FAILED! => {"changed": false, "module_stderr": "Traceback (most recent call last):\n  File \"/home/user/.ansible/tmp/ansible-tmp-1602932173.7323837-24457-268203592954263/AnsiballZ_port_description.py\", line 102, in <module>\n    _ansiballz_main()\n  File \"/home/user/.ansible/tmp/ansible-tmp-1602932173.7323837-24457-268203592954263/AnsiballZ_port_description.py\", line 94, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/home/user/.ansible/tmp/ansible-tmp-1602932173.7323837-24457-268203592954263/AnsiballZ_port_description.py\", line 40, in invoke_module\n    runpy.run_module(mod_name='ansible.modules.port_description', init_globals=None, run_name='__main__', alter_sys=True)\n  File \"/usr/lib/python3.6/runpy.py\", line 205, in run_module\n    return _run_module_code(code, init_globals, run_name, mod_spec)\n  File \"/usr/lib/python3.6/runpy.py\", line 96, in _run_module_code\n    mod_name, mod_spec, pkg_name, script_name)\n  File \"/usr/lib/python3.6/runpy.py\", line 85, in _run_code\n    exec(code, run_globals)\n  File \"/tmp/ansible_port_description_payload_6v82vnu_/ansible_port_description_payload.zip/ansible/modules/port_description.py\", line 48, in <module>\n  File \"/tmp/ansible_port_description_payload_6v82vnu_/ansible_port_description_payload.zip/ansible/modules/port_description.py\", line 22, in main\nFileNotFoundError: [Errno 2] No such file or directory: 'CSV_TEST.csv'\n", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}

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