modal-labs / modal-client

Python client library for Modal
https://modal.com/docs
Apache License 2.0
271 stars 35 forks source link

Client-side app-less sandboxes #1957

Closed erikbern closed 3 months ago

erikbern commented 3 months ago

Implements the basics of this. Demo:

>>> from modal import Sandbox
>>> s = Sandbox.create("/bin/bash", "-c", "echo hello world")
>>> for line in s.stdout:
...     print(line)
... 
hello world

>>> s.poll()
0

TODO for this PR:

Will do in subsequent PRs:

erikbern commented 3 months ago

Ok slightly bad news: in order for this to work, we need to support app-less secrets and mounts as well.

The good news is that this is something I've been hoping to add support for anyway for a while. But it will take a bit of time to figure out how to do it, unfortunately.

erikbern commented 3 months ago

LGTM! Should we add a deprecation message for the old code path?

Was planning to do that in a subsequent PR (I want to update some integration tests and docs first)

erikbern commented 3 months ago

This works now, but lack of output is a bit confusing with custom images.

>>> image = Image.debian_slim().pip_install("numpy").run_commands("sleep 30")
>>> s = Sandbox.create("/bin/bash", "-c", "echo hello world", image=image)  # This blocks for >30s
>>> s.poll()
0
>>> [line for line in s.stdout]
['hello world\n']
aksh-at commented 3 months ago

This works now, but lack of output is a bit confusing with custom images.

Ah yeah, I think we used to be able to see output in the app logs, but decoupling makes that difficult 🤔

erikbern commented 3 months ago

Ah yeah, I think we used to be able to see output in the app logs, but decoupling makes that difficult 🤔

I think we can fix this in a different way. I've had it on my backlog for a long time to break out the output management into a singleton (separate from the resolver) that you can activate using a context manager (with the idea that all CLI commands enable this automatically). Something like

with modal.enable_logs():
    ...

I don't love singletons but in this case I think it's fine since stdout is already a singleton

erikbern commented 3 months ago

ok this FINALLY works

>>> from modal import Image, Secret, Mount, Sandbox
>>> secret = Secret.from_dict({"FOO": "bar"})
>>> s = Sandbox.create("/bin/bash", "-c", "echo $FOO", secrets=[secret], environment_name="main")
>>> s.poll()
0
>>> [line for line in s.stdout]
['bar\n']