Skip to content

Commit

Permalink
Allow run::bind config to specify different destination
Browse files Browse the repository at this point in the history
Until now, the directories mentioned in this config key have always been
mounted at the same absolute path in the container as they exist on the
host. Extend this to allow a different destination path in the container:

  ...
  [run]
  bind =
    ...
    /src-path:/dst-path
    ...

All of the usual options already recognized are valid for entries
specified using this expanded syntax.

Change-Id: Iaa0e70325f576d71ea672da082ce1a76c9c81c94
  • Loading branch information
matthoosier-garmin authored and JoshuaWatt committed Jul 25, 2024
1 parent 37a1f12 commit c617275
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 8 deletions.
26 changes: 26 additions & 0 deletions ci/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,32 @@ def test_bad_bind_option(self):
)
self.assertIn("Error: bad option(s) 'bad-option' for bind", s)

def test_bind_dest(self):
temp_dir = tempfile.mkdtemp("-pyrex")
self.addCleanup(shutil.rmtree, temp_dir)

temp_file = os.path.join(temp_dir, "data")

conf = self.get_config()
conf["run"]["bind"] += " %s:/foo" % (temp_dir)
conf.write_conf()

self.assertPyrexContainerShellCommand("echo 123 > /foo/data")

with open(temp_file, "r") as f:
self.assertEqual(f.read(), "123\n")

def test_malformed_bind_dest(self):

b = "/src:/dst:illegal-token"

conf = self.get_config()
conf["run"]["bind"] += " %s" % b
conf.write_conf()

s = self.assertPyrexContainerShellCommand("true", capture=True, returncode=1)
self.assertIn("Error: too many colons in run.bind entry '%s'." % b, s)

def test_bad_confversion(self):
# Verify that a bad config is an error
conf = self.get_config()
Expand Down
37 changes: 29 additions & 8 deletions pyrex.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ def __init__(self, *args, **kwargs):
self.optionxform = lambda option: option


class ParsingError(Exception):
pass


def read_default_config(keep_defaults):
with open(os.path.join(PYREX_ROOT, "pyrex.ini"), "r") as f:
line = f.read().replace("@CONFVERSION@", PYREX_CONFVERSION)
Expand Down Expand Up @@ -346,7 +350,23 @@ def parse_bind_options(bind):
else:
bad_options.append(opt)

return bind, options, bad_options
if bad_options:
raise ParsingError(
"bad option(s) '%s' for bind %s" % (" ".join(bad_options), bind)
)

binds = bind.split(":")

if len(binds) > 2:
raise ParsingError("too many colons in run.bind entry '%s'." % bind)
elif len(binds) == 1:
src = bind
dst = bind
else:
src = binds[0]
dst = binds[1]

return src, dst, options


def prep_container(
Expand Down Expand Up @@ -528,22 +548,23 @@ def prep_container(
+ extra_bind
)
for b in set(binds):
b, options, bad_options = parse_bind_options(b)
if bad_options:
print("Error: bad option(s) '%s' for bind %s" % (" ".join(bad_options), b))
try:
src, dst, options = parse_bind_options(b)
except ParsingError as e:
print("Error: %s" % e)
return []

if not os.path.exists(b):
if not os.path.exists(src):
if options.optional:
continue
print("Error: bind source path {b} does not exist".format(b=b))
print("Error: bind source path {src} does not exist".format(src=src))
return []

engine_args.extend(
[
"--mount",
"type=bind,src={b},dst={b}{ro}".format(
b=b, ro=",readonly" if options.readonly else ""
"type=bind,src={src},dst={dst}{ro}".format(
src=src, dst=dst, ro=",readonly" if options.readonly else ""
),
]
)
Expand Down

0 comments on commit c617275

Please sign in to comment.