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.

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
Is the
sftpmodule something that you wrote? In the error message, we see it failing with thisFileNotFoundErrorexception:It's looking for
/devops/junk.txton the local machine, but from your playbook it looks like you're trying to retrieve that file from the remote machine.It looks like
srcanddestare getting mixed up, or the code isn't respecting the value of thedirectionattribute.