Search code examples
python-3.xansibleparamiko

Ansible module succeeds on my Mac, but fails on a Rock Linux box?


I created an Ansible module shown on this post Pass/fail result for Paramiko SFTPClient get() and put() functions? Here's a simple playbook to test the module.

- hosts: localhost
  tasks:
    - name: Test that my module works
      sftp:
        host: "{{ sftp_url }}"
        user: "{{ sftp_user }}"
        password: "{{ sftp_password }}"
        src: "/devops/junk.txt"
        dest: "/tmp/junk.txt"
        direction: download
      register: result
      delegate_to: localhost

I'm able to run it successfully on my Mac and o Ubuntu Linux. However, when I run it on a Rocky Linux box, I get

2024-02-01 17:42:32,518 p=1787 u=jenkins n=ansible | [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

2024-02-01 17:42:32,748 p=1787 u=jenkins n=ansible | PLAY [localhost] ***********************************************************************************************************************************************
2024-02-01 17:42:32,792 p=1787 u=jenkins n=ansible | TASK [Gathering Facts] *****************************************************************************************************************************************
2024-02-01 17:42:34,060 p=1787 u=jenkins n=ansible | ok: [localhost]
2024-02-01 17:42:34,095 p=1787 u=jenkins n=ansible | TASK [Test SFTP] ***********************************************************************************************************************************************
2024-02-01 17:42:35,086 p=1787 u=jenkins n=ansible | An exception occurred during task execution. To see the full traceback, use -vvv. The error was: FileNotFoundError: [Errno 2] No such file or directory: '/devops/junk.txt'
2024-02-01 17:42:35,100 p=1787 u=jenkins n=ansible | fatal: [localhost]: FAILED! => {"changed": false, "module_stderr": "Traceback (most recent call last):\n  File \"/home/jenkins/.ansible/tmp/ansible-tmp-1706827354.125057-1845-53715366175385/AnsiballZ_sftp.py\", line 107, in <module>\n    _ansiballz_main()\n  File \"/home/jenkins/.ansible/tmp/ansible-tmp-1706827354.125057-1845-53715366175385/AnsiballZ_sftp.py\", line 99, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/home/jenkins/.ansible/tmp/ansible-tmp-1706827354.125057-1845-53715366175385/AnsiballZ_sftp.py\", line 47, in invoke_module\n    runpy.run_module(mod_name='ansible.modules.sftp', init_globals=dict(_module_fqn='ansible.modules.sftp', _modlib_path=modlib_path),\n  File \"/usr/lib64/python3.9/runpy.py\", line 225, in run_module\n    return _run_module_code(code, init_globals, run_name, mod_spec)\n  File \"/usr/lib64/python3.9/runpy.py\", line 97, in _run_module_code\n    _run_code(code, mod_globals, init_globals,\n  File \"/usr/lib64/python3.9/runpy.py\", line 87, in _run_code\n    exec(code, run_globals)\n  File \"/tmp/ansible_sftp_payload_w5bn7ztl/ansible_sftp_payload.zip/ansible/modules/sftp.py\", line 67, in <module>\n  File \"/tmp/ansible_sftp_payload_w5bn7ztl/ansible_sftp_payload.zip/ansible/modules/sftp.py\", line 62, in main\n  File \"/tmp/ansible_sftp_payload_w5bn7ztl/ansible_sftp_payload.zip/ansible/modules/sftp.py\", line 30, in transfer_file\n  File \"/home/jenkins/.local/lib/python3.9/site-packages/paramiko/sftp_client.py\", line 757, in put\n    file_size = os.stat(localpath).st_size\nFileNotFoundError: [Errno 2] No such file or directory: '/devops/junk.txt'\n", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}
2024-02-01 17:42:35,113 p=1787 u=jenkins n=ansible | PLAY RECAP *****************************************************************************************************************************************************
2024-02-01 17:42:35,119 p=1787 u=jenkins n=ansible | localhost                  : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

The file is definitely there of course. Here's a screenshot. enter image description here

Any clues? Thanks!

UPDATE

Here is the SAME playbook when run on my Mac.

$ ls /devops
ls: /devops: No such file or directory

$ ls /tmp
(shows nothing)

$ ansible-playbook sftp.yml 
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

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

TASK [Gathering Facts] ****************************************************************************************************************************
ok: [localhost]

TASK [Test that my module works] ******************************************************************************************************************
changed: [localhost]

TASK [debug] **************************************************************************************************************************************
ok: [localhost] => {
    "result": {
        "changed": true,
        "failed": false,
        "meta": {
            "dest": "/tmp/junk.txt",
            "direction": "download",
            "src": "/devops/junk.txt",
            "status": "success"
        }
    }
}

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

$ ls /tmp
ansible.log junk.txt 

Solution

  • Is the sftp module something that you wrote? In the error message, we see it failing with this FileNotFoundError exception:

          File \"/home/jenkins/.local/lib/python3.9/site-packages/paramiko/sftp_client.py\", line 757, in put
            file_size = os.stat(localpath).st_size
        FileNotFoundError: [Errno 2] No such file or directory: '/devops/junk.txt'
    

    It's looking for /devops/junk.txt on the local machine, but from your playbook it looks like you're trying to retrieve that file from the remote machine.

    It looks like src and dest are getting mixed up, or the code isn't respecting the value of the direction attribute.