Skip to content

Commit 44f3a22

Browse files
Better handle situations where the parent directory doesn't exist during sftp (#175)
This change adds some additional logic to not only handle when parent directories don't exist, but also constructs the destination path when only a directory is given Fixes #169
1 parent fca5b61 commit 44f3a22

File tree

3 files changed

+27
-10
lines changed

3 files changed

+27
-10
lines changed

broker/session.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ def sftp_read(self, source, destination=None):
8181
"""read a remote file into a local destination"""
8282
if not destination:
8383
destination = source
84+
elif destination.endswith("/"):
85+
destination = destination + Path(source).name
8486
# create the destination path if it doesn't exist
8587
destination = Path(destination)
8688
destination.parent.mkdir(parents=True, exist_ok=True)
@@ -94,30 +96,38 @@ def sftp_read(self, source, destination=None):
9496
for size, data in remote:
9597
local.write(data)
9698

97-
def sftp_write(self, source, destination=None):
99+
def sftp_write(self, source, destination=None, ensure_dir=True):
98100
"""sftp write a local file to a remote destination"""
99101
if not destination:
100102
destination = source
103+
elif destination.endswith("/"):
104+
destination = destination + Path(source).name
101105
data = Path(source).read_bytes()
106+
if ensure_dir:
107+
self.run(f"mkdir -p {Path(destination).absolute().parent}")
102108
sftp = self.session.sftp_init()
103109
with sftp.open(destination, FILE_FLAGS, SFTP_MODE) as remote:
104110
remote.write(data)
105111

106-
def remote_copy(self, source, dest_host):
112+
def remote_copy(self, source, dest_host, ensure_dir=True):
107113
"""Copy a file from this host to another"""
108114
sftp_down = self.session.sftp_init()
109115
sftp_up = dest_host.session.session.sftp_init()
116+
if ensure_dir:
117+
dest_host.run(f"mkdir -p {Path(source).absolute().parent}")
110118
with sftp_down.open(
111119
source, ssh2_sftp.LIBSSH2_FXF_READ, ssh2_sftp.LIBSSH2_SFTP_S_IRUSR
112120
) as download:
113121
with sftp_up.open(source, FILE_FLAGS, SFTP_MODE) as upload:
114122
for size, data in download:
115123
upload.write(data)
116124

117-
def scp_write(self, source, destination=None):
125+
def scp_write(self, source, destination=None, ensure_dir=True):
118126
"""scp write a local file to a remote destination"""
119127
if not destination:
120128
destination = source
129+
elif destination.endswith("/"):
130+
destination = destination + Path(source).name
121131
fileinfo = os.stat(source)
122132
chan = self.session.scp_send64(
123133
destination,
@@ -126,6 +136,8 @@ def scp_write(self, source, destination=None):
126136
fileinfo.st_mtime,
127137
fileinfo.st_atime,
128138
)
139+
if ensure_dir:
140+
self.run(f"mkdir -p {Path(destination).absolute().parent}")
129141
with open(source, "rb") as local:
130142
for data in local:
131143
chan.write(data)
@@ -221,7 +233,7 @@ def disconnect(self):
221233
"""Needed for simple compatability with Session"""
222234
pass
223235

224-
def sftp_write(self, source, destination=None):
236+
def sftp_write(self, source, destination=None, ensure_dir=True):
225237
"""Add one of more files to the container"""
226238
# ensure source is a list of Path objects
227239
if not isinstance(source, list):
@@ -232,15 +244,17 @@ def sftp_write(self, source, destination=None):
232244
for src in source:
233245
if not Path(src).exists():
234246
raise FileNotFoundError(src)
235-
destination = Path(destination) or source[0].parent
247+
destination = destination or f"{source[0].parent}/"
236248
# Files need to be added to a tarfile
237249
with helpers.temporary_tar(source) as tar:
238250
logger.debug(
239251
f"{self._cont_inst.hostname} adding file(s) {source} to {destination}"
240252
)
241-
# if the destination is a file, create the parent path
242-
if destination.is_file():
243-
self.execute(f"mkdir -p {destination.parent}")
253+
if ensure_dir:
254+
if destination.endswith("/"):
255+
self.run(f"mkdir -m 666 -p {destination}")
256+
else:
257+
self.run(f"mkdir -m 666 -p {Path(destination).parent}")
244258
self._cont_inst._cont_inst.put_archive(str(destination), tar.read_bytes())
245259

246260
def sftp_read(self, source, destination=None):

tests/functional/test_containers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,6 @@ def test_container_e2e_mp():
8484
res = c_host.execute("hostname")
8585
assert res.stdout.strip() == c_host.hostname
8686
# Test that a file can be uploaded to the container
87-
c_host.session.sftp_write("broker_settings.yaml", "/root")
88-
res = c_host.execute("ls")
87+
c_host.session.sftp_write("broker_settings.yaml", "/tmp/fake/")
88+
res = c_host.execute("ls /tmp/fake")
8989
assert "broker_settings.yaml" in res.stdout

tests/functional/test_satlab.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,6 @@ def test_tower_host():
6868
with Broker(workflow="deploy-base-rhel") as r_host:
6969
res = r_host.execute("hostname")
7070
assert res.stdout.strip() == r_host.hostname
71+
r_host.session.sftp_write("broker_settings.yaml", "/tmp/fake/")
72+
res = r_host.execute("ls /tmp/fake")
73+
assert "broker_settings.yaml" in res.stdout

0 commit comments

Comments
 (0)