Skip to content

Commit

Permalink
Merge branch 'main' of github.com:modal-labs/modal-client into kramst…
Browse files Browse the repository at this point in the history
…rom/mod-2454-remove-aiostream-dependency-async_map
  • Loading branch information
kramstrom committed Oct 28, 2024
2 parents 566e7ca + e1540bf commit 1bc20c7
Show file tree
Hide file tree
Showing 12 changed files with 58 additions and 18 deletions.
4 changes: 4 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
}
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ We appreciate your patience while we speedily work towards a stable release of t

<!-- NEW CONTENT GENERATED BELOW. PLEASE PRESERVE THIS COMMENT. -->

### 0.64.227 (2024-10-25)

- The `modal container list` CLI command now only shows containers for the active profile's environment if there is one, otherwise it uses the default environment. You can pass `--env` to list containers in other environments.

### 0.64.223 (2024-10-24)

* Fix for `modal serve` not showing progress when reloading apps on file changes since v0.63.79
Expand Down
14 changes: 9 additions & 5 deletions modal/cli/config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Copyright Modal Labs 2022
import pprint

import typer
from rich.console import Console

from modal.config import _profile, _store_user_config, config

Expand All @@ -17,10 +16,15 @@
)


@config_cli.command(help="Show configuration values for the current profile (debug command).")
def show():
@config_cli.command(help="Show current configuration values (debugging command).")
def show(redact: bool = typer.Option(True, help="Redact the `token_secret` value.")):
# This is just a test command
pprint.pprint(config.to_dict())
config_dict = config.to_dict()
if redact and config_dict.get("token_secret"):
config_dict["token_secret"] = "***"

console = Console()
console.print(config_dict)


SET_DEFAULT_ENV_HELP = """Set the default Modal environment for the active profile
Expand Down
5 changes: 5 additions & 0 deletions modal/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,11 @@ async def from_env(cls, _override_config=None) -> "_Client":
token_id = c["token_id"]
token_secret = c["token_secret"]
if task_secret:
if token_id or token_secret:
warnings.warn(
"Modal tokens provided by MODAL_TOKEN_ID and MODAL_TOKEN_SECRET"
" (or through the config file) are ignored inside containers."
)
client_type = api_pb2.CLIENT_TYPE_CONTAINER
credentials = None
elif token_id and token_secret:
Expand Down
8 changes: 3 additions & 5 deletions modal/proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@


class _Proxy(_Object, type_prefix="pr"):
"""
Proxy objects are used to setup secure tunnel connections to a private remote address, for example
a database.
"""Proxy objects give your Modal containers a static outbound IP address.
Currently `modal.Proxy` objects must be setup with the assistance of Modal staff. If you require a proxy
please contact us.
This can be used for connecting to a remote address with network whitelist, for example
a database. See [the guide](/docs/guide/proxy-ips) for more information.
"""

@staticmethod
Expand Down
1 change: 1 addition & 0 deletions modal_proto/api.proto
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ enum CheckpointStatus {
enum ClientType {
CLIENT_TYPE_UNSPECIFIED = 0;
CLIENT_TYPE_CLIENT = 1;
CLIENT_TYPE_WORKER = 2;
CLIENT_TYPE_CONTAINER = 3;
CLIENT_TYPE_WEB_SERVER = 5;
}
Expand Down
2 changes: 1 addition & 1 deletion modal_version/_version_generated.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright Modal Labs 2024

# Note: Reset this value to -1 whenever you make a minor `0.X` release of the client.
build_number = 227 # git: 2fe452c
build_number = 233 # git: 76f36d3
4 changes: 4 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ install_requires =
watchfiles
typing_extensions~=4.6

[options.packages.find]
exclude =
test*

[options.entry_points]
console_scripts =
modal = modal.__main__:main
Expand Down
13 changes: 13 additions & 0 deletions test/cli_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,19 @@ def test_profile_list(servicer, server_url_env, modal_config):
del os.environ["MODAL_TOKEN_SECRET"]


def test_config_show(servicer, server_url_env, modal_config):
config = """
[test-profile]
token_id = "ak-abc"
token_secret = "as-xyz"
active = true
"""
with modal_config(config):
res = _run(["config", "show"])
assert "'token_id': 'ak-abc'" in res.stdout
assert "'token_secret': '***'" in res.stdout


def test_app_list(servicer, mock_dir, set_env_client):
res = _run(["app", "list"])
assert "my_app_foo" not in res.stdout
Expand Down
16 changes: 11 additions & 5 deletions test/client_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
def test_client_type(servicer, client):
assert len(servicer.requests) == 1
assert isinstance(servicer.requests[0], Empty)
assert servicer.client_create_metadata["x-modal-client-type"] == str(api_pb2.CLIENT_TYPE_CLIENT)
assert servicer.last_metadata["x-modal-client-type"] == str(api_pb2.CLIENT_TYPE_CLIENT)


def test_client_platform_string(servicer, client):
platform_str = servicer.client_create_metadata["x-modal-platform"]
platform_str = servicer.last_metadata["x-modal-platform"]
system, release, machine = platform_str.split("-")
if platform.system() == "Darwin":
assert system == "macOS"
Expand All @@ -39,7 +39,7 @@ def test_client_platform_string(servicer, client):
async def test_container_client_type(servicer, container_client):
assert len(servicer.requests) == 1 # no heartbeat, just ClientHello
assert isinstance(servicer.requests[0], Empty)
assert servicer.client_create_metadata["x-modal-client-type"] == str(api_pb2.CLIENT_TYPE_CONTAINER)
assert servicer.last_metadata["x-modal-client-type"] == str(api_pb2.CLIENT_TYPE_CONTAINER)


@pytest.mark.asyncio
Expand Down Expand Up @@ -160,7 +160,7 @@ def test_client_token_auth_in_container(servicer, credentials, monkeypatch) -> N
"""
monkeypatch.setenv("MODAL_IS_REMOTE", "1")
_client = client_from_env(servicer.client_addr, credentials)
assert servicer.client_create_metadata["x-modal-client-type"] == str(api_pb2.CLIENT_TYPE_CLIENT)
assert servicer.last_metadata["x-modal-client-type"] == str(api_pb2.CLIENT_TYPE_CLIENT)


def test_multiple_profile_error(servicer, modal_config):
Expand Down Expand Up @@ -216,12 +216,16 @@ def test_from_env_container(servicer, container_env):
servicer.required_creds = {} # Disallow default client creds
Client.from_env()
# TODO(erikbern): once we no longer run ClientHello by default, add a ping here
assert servicer.last_metadata["x-modal-client-type"] == str(api_pb2.CLIENT_TYPE_CONTAINER)


def test_from_env_container_with_tokens(servicer, container_env, token_env):
# Even if MODAL_TOKEN_ID and MODAL_TOKEN_SECRET are set, if we're in a containers, ignore those
servicer.required_creds = {} # Disallow default client creds
Client.from_env()
with pytest.warns(match="token"):
Client.from_env()
# TODO(erikbern): once we no longer run ClientHello by default, add a ping here
assert servicer.last_metadata["x-modal-client-type"] == str(api_pb2.CLIENT_TYPE_CONTAINER)


def test_from_credentials_client(servicer, set_env_client, server_url_env, token_env):
Expand All @@ -231,6 +235,7 @@ def test_from_credentials_client(servicer, set_env_client, server_url_env, token
servicer.required_creds = {token_id: token_secret}
Client.from_credentials(token_id, token_secret)
# TODO(erikbern): once we no longer run ClientHello by default, add a ping here
assert servicer.last_metadata["x-modal-client-type"] == str(api_pb2.CLIENT_TYPE_CLIENT)


def test_from_credentials_container(servicer, container_env):
Expand All @@ -239,3 +244,4 @@ def test_from_credentials_container(servicer, container_env):
servicer.required_creds = {token_id: token_secret}
Client.from_credentials(token_id, token_secret)
# TODO(erikbern): once we no longer run ClientHello by default, add a ping here
assert servicer.last_metadata["x-modal-client-type"] == str(api_pb2.CLIENT_TYPE_CLIENT)
2 changes: 1 addition & 1 deletion test/config_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def _cli(args, env={}):


def _get_config(env={}):
stdout = _cli(["config", "show"], env=env)
stdout = _cli(["config", "show", "--no-redact"], env=env)
return eval(stdout)


Expand Down
3 changes: 2 additions & 1 deletion test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,13 +247,15 @@ def __init__(self, blob_host, blobs, credentials):

token_id, token_secret = credentials
self.required_creds = {token_id: token_secret} # Any of this will be accepted
self.last_metadata = None

@self.function_body
def default_function_body(*args, **kwargs):
return sum(arg**2 for arg in args) + sum(value**2 for key, value in kwargs.items())

async def recv_request(self, event: RecvRequest):
# Make sure metadata is correct
self.last_metadata = event.metadata
for header in [
"x-modal-python-version",
"x-modal-client-version",
Expand Down Expand Up @@ -642,7 +644,6 @@ async def ClassGet(self, stream):
async def ClientHello(self, stream):
request: Empty = await stream.recv_message()
self.requests.append(request)
self.client_create_metadata = stream.metadata
client_version = stream.metadata["x-modal-client-version"]
warning = ""
assert stream.user_agent.startswith(f"modal-client/{__version__} ")
Expand Down

0 comments on commit 1bc20c7

Please sign in to comment.