pyinfra
pyinfra copied to clipboard
files.put to a readonly filesystem does not fail in a clear way
The error for trying to files.put to a readonly filesystem is confusing, and actions continue afterwards in a surprising way:
(on host slash
, / is mounted ro for some reason)
--> Beginning operation run...
--> Starting operation: Files/Put (dest=/usr/local/bin/k3s-killall.sh, src=files/kube/k3s-killall.sh, mode=a+rx)
[prime] Skipped
[dot] Skipped
[garage] Skipped
[bang] Skipped
[pipe] Skipped
[dash] file uploaded: /usr/local/bin/k3s-killall.sh
[dash] >>> sh -c 'chmod a+rx /usr/local/bin/k3s-killall.sh'
Failed to upload file, retrying: Failure
[slash] file uploaded: /usr/local/bin/k3s-killall.sh
[slash] >>> sh -c 'chmod a+rx /usr/local/bin/k3s-killall.sh'
[dash] Success
[slash] chmod: cannot access '/usr/local/bin/k3s-killall.sh': No such file or directory
[slash] Error
I did not expect things to continue after 'failed to upload file'.
The ideal message here would be like "[slash] /usr/local/bin is on a readonly filesystem".
Interesting - looks like the result of the upload function was a success despite the error! Thank you for raising this I’ll get a repro working and fix.
Hm, finally testing this but it seems to be working correctly, firstly created a container with a read only dir:
docker run -it -v `pwd`:/opt/pyinfra:ro ubuntu
Then tried to use files.put
on it:
pyinfra @docker/64008a0b1685 files.put setup.py /opt/pyinfra/file
--> Loading config...
--> Loading inventory...
--> Connecting to hosts...
[@docker/64008a0b1685] Connected
--> Preparing operation...
[@docker/64008a0b1685] Ready: files.put
--> Proposed changes:
Groups: @docker
[@docker/64008a0b1685] Operations: 1 Change: 1 No change: 0
--> Beginning operation run...
--> Starting operation: Files/Put (setup.py, /opt/pyinfra/file)
[@docker/64008a0b1685] Command socket/SSH error: OSError('Error response from daemon: mounted volume is marked read-only',)
[@docker/64008a0b1685] Error: executed 0/1 commands
[@docker/64008a0b1685] docker build complete, container left running: 64008a0b1685
--> pyinfra error: No hosts remaining!
The upload code does re-attempt uploads 3 times, in the above it looks like it failed once and subsequently claimed to work, even though the file clearly wasn't there:
https://github.com/Fizzadar/pyinfra/blob/7cc0e02149106d561df3f6acba390e20b7f7c1c5/pyinfra/connectors/ssh.py#L472-L483
Even more concerning is paramiko appears to do a stat
check on the file after uploading by default (https://docs.paramiko.org/en/stable/api/sftp.html#paramiko.sftp_client.SFTPClient.putfo).
I wonder if this is limited to situations where /
is read-only... I need to use a test VM/server to do that which I currently cannot access unfortunately but when I can I will try it out.
v2.6.1 should fix the false positive success here, my bad for not spotting this before! More @ https://github.com/Fizzadar/pyinfra/issues/936#issuecomment-1368192388