Skip to content

Commit ed81b05

Browse files
authored
Do not request image config for default images (#3684)
Do not request the Docker image config for our default images when determining the user, since we know that our images do not set it. This helps avoid hitting Docker Hub's rate limits.
1 parent a1d9703 commit ed81b05

2 files changed

Lines changed: 70 additions & 1 deletion

File tree

  • src
    • dstack/_internal/server/services/jobs/configurators
    • tests/_internal/server/services/jobs

src/dstack/_internal/server/services/jobs/configurators/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ def _image_name(self) -> str:
280280

281281
async def _user(self) -> Optional[UnixUser]:
282282
user = self.run_spec.configuration.user
283-
if user is None:
283+
if user is None and self.run_spec.configuration.image is not None:
284284
image_config = await self._get_image_config()
285285
user = image_config.user
286286
if user is None:
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
from unittest.mock import patch
2+
3+
import pytest
4+
5+
from dstack._internal.core.models.configurations import TaskConfiguration
6+
from dstack._internal.core.models.profiles import Profile
7+
from dstack._internal.core.models.repos.local import LocalRunRepoData
8+
from dstack._internal.core.models.runs import RunSpec
9+
from dstack._internal.server.services.docker import ImageConfig
10+
from dstack._internal.server.services.jobs import get_job_specs_from_run_spec
11+
12+
13+
@pytest.mark.parametrize(
14+
"configuration, expected_calls",
15+
[
16+
pytest.param(
17+
# No need to request the registry if our default image is used.
18+
TaskConfiguration(commands=["sleep infinity"]),
19+
0,
20+
id="default-dstack-image",
21+
),
22+
pytest.param(
23+
TaskConfiguration(image="ubuntu"),
24+
1,
25+
id="custom-image",
26+
),
27+
pytest.param(
28+
TaskConfiguration(image="ubuntu", commands=["sleep infinity"]),
29+
1,
30+
id="custom-image-with-commands",
31+
),
32+
pytest.param(
33+
TaskConfiguration(image="ubuntu", user="root"),
34+
1,
35+
id="custom-image-with-user",
36+
),
37+
pytest.param(
38+
# Setting `commands` and `user` is a known hack that we advertised to some customers
39+
# to avoid registry requests.
40+
TaskConfiguration(image="ubuntu", commands=["sleep infinity"], user="root"),
41+
0,
42+
id="custom-image-with-commands-and-user",
43+
),
44+
],
45+
)
46+
@pytest.mark.asyncio
47+
async def test_get_job_specs_from_run_spec_image_config_calls(
48+
configuration: TaskConfiguration, expected_calls: int
49+
) -> None:
50+
"""
51+
Test the number of times we attempt to fetch the image config from the Docker registry.
52+
53+
Whenever possible, we prefer not to request the registry to avoid hitting rate limits.
54+
"""
55+
56+
run_spec = RunSpec(
57+
run_name="test-run",
58+
repo_data=LocalRunRepoData(repo_dir="/"),
59+
configuration=configuration,
60+
profile=Profile(name="default"),
61+
ssh_key_pub="user_ssh_key",
62+
)
63+
fake_image_config = ImageConfig.parse_obj({"Entrypoint": ["/bin/bash"]})
64+
with patch(
65+
"dstack._internal.server.services.jobs.configurators.base._get_image_config",
66+
return_value=fake_image_config,
67+
) as mock_get_image_config:
68+
await get_job_specs_from_run_spec(run_spec=run_spec, secrets={}, replica_num=0)
69+
assert mock_get_image_config.call_count == expected_calls

0 commit comments

Comments
 (0)