@@ -87,17 +87,37 @@ async def test_first_mirror_hit_rewrites_image(restore_sandbox_manager, stub_man
8787 ]
8888 )
8989 config = DockerDeploymentConfig (image = "gcr.io/foo/python:3.11" )
90+ # First probe: registry-only (preserve original namespace "foo") -> hit
9091 stub_manifest_probe .probe_results .append (True )
9192
9293 await sandbox_api ._apply_image_registry_mirror (config )
9394
94- assert config .image == "rock-a.example.com/rock-public /python:3.11"
95+ assert config .image == "rock-a.example.com/foo /python:3.11"
9596 assert config .registry_username is None
9697 assert config .registry_password is None
9798 assert len (stub_manifest_probe .probes ) == 1
99+ assert stub_manifest_probe .probes [0 ]["repo" ] == "foo/python"
100+
101+
102+ async def test_registry_only_miss_falls_back_to_namespace_replace (restore_sandbox_manager , stub_manifest_probe ):
103+ sandbox_api .sandbox_manager = _make_manager (
104+ [ImageRegistryMirror (registry = "rock-a.example.com" , namespace = "rock-public" )]
105+ )
106+ config = DockerDeploymentConfig (image = "gcr.io/foo/python:3.11" )
107+ # First probe: registry-only (foo/python) -> miss
108+ # Second probe: registry+namespace (rock-public/python) -> hit
109+ stub_manifest_probe .probe_results .extend ([False , True ])
110+
111+ await sandbox_api ._apply_image_registry_mirror (config )
112+
113+ assert config .image == "rock-a.example.com/rock-public/python:3.11"
114+ assert len (stub_manifest_probe .probes ) == 2
115+ assert stub_manifest_probe .probes [0 ]["repo" ] == "foo/python"
116+ assert stub_manifest_probe .probes [1 ]["repo" ] == "rock-public/python"
98117
99118
100119async def test_second_mirror_hit_after_first_miss (restore_sandbox_manager , stub_manifest_probe ):
120+ """No original namespace (bare image) — only namespace-replace candidates are tried."""
101121 sandbox_api .sandbox_manager = _make_manager (
102122 [
103123 ImageRegistryMirror (registry = "rock-a.example.com" , namespace = "rock-public" ),
@@ -114,6 +134,7 @@ async def test_second_mirror_hit_after_first_miss(restore_sandbox_manager, stub_
114134
115135
116136async def test_full_miss_keeps_original_image (restore_sandbox_manager , stub_manifest_probe ):
137+ """No original namespace — each mirror has 1 candidate, both miss."""
117138 sandbox_api .sandbox_manager = _make_manager (
118139 [
119140 ImageRegistryMirror (registry = "rock-a.example.com" , namespace = "rock-public" ),
@@ -208,17 +229,22 @@ async def test_invalid_mirror_entry_skipped(restore_sandbox_manager, stub_manife
208229
209230
210231async def test_candidate_strips_registry_and_namespace_preserves_repo (restore_sandbox_manager , stub_manifest_probe ):
232+ """With original namespace 'project', first probe keeps it, second uses mirror namespace."""
211233 sandbox_api .sandbox_manager = _make_manager (
212234 [ImageRegistryMirror (registry = "rock-a.example.com" , namespace = "rock-public" )]
213235 )
214236 config = DockerDeploymentConfig (image = "gcr.io/project/subdir/myimage:v1" )
215- stub_manifest_probe .probe_results .append (False )
237+ # First probe: registry-only (project/subdir/myimage) -> miss
238+ # Second probe: registry+namespace (rock-public/subdir/myimage) -> miss
239+ stub_manifest_probe .probe_results .extend ([False , False ])
216240
217241 await sandbox_api ._apply_image_registry_mirror (config )
218242
219- assert stub_manifest_probe .probes [0 ]["image" ] == "rock-a.example.com/rock-public /subdir/myimage:v1"
220- assert stub_manifest_probe .probes [0 ]["repo" ] == "rock-public /subdir/myimage"
243+ assert stub_manifest_probe .probes [0 ]["image" ] == "rock-a.example.com/project /subdir/myimage:v1"
244+ assert stub_manifest_probe .probes [0 ]["repo" ] == "project /subdir/myimage"
221245 assert stub_manifest_probe .probes [0 ]["tag" ] == "v1"
246+ assert stub_manifest_probe .probes [1 ]["image" ] == "rock-a.example.com/rock-public/subdir/myimage:v1"
247+ assert stub_manifest_probe .probes [1 ]["repo" ] == "rock-public/subdir/myimage"
222248
223249
224250async def test_missing_tag_defaults_to_latest (restore_sandbox_manager , stub_manifest_probe ):
@@ -371,12 +397,13 @@ async def test_wildcard_allowlist_lets_every_image_through(restore_sandbox_manag
371397 [ImageRegistryMirror (registry = "rock-a.example.com" , namespace = "rock-public" )],
372398 allowlist = ["*" ],
373399 )
400+ # First probe: registry-only (foo/python) -> hit
374401 stub_manifest_probe .probe_results .append (True )
375402 config = DockerDeploymentConfig (image = "gcr.io/foo/python:3.11" )
376403
377404 await sandbox_api ._apply_image_registry_mirror (config )
378405
379- assert config .image == "rock-a.example.com/rock-public /python:3.11"
406+ assert config .image == "rock-a.example.com/foo /python:3.11"
380407 assert len (stub_manifest_probe .probes ) == 1
381408
382409
@@ -385,12 +412,16 @@ async def test_prefix_allowlist_matches_only_listed_images(restore_sandbox_manag
385412 [ImageRegistryMirror (registry = "rock-a.example.com" , namespace = "rock-public" )],
386413 allowlist = ["aaaaaa/bbb/" , "swe-bench:" ],
387414 )
388- stub_manifest_probe .probe_results .extend ([True , True ])
415+ # "aaaaaa/bbb/swe-bench:..." has original_namespace="aaaaaa":
416+ # 1st probe: registry-only (aaaaaa/bbb/swe-bench) -> hit
417+ stub_manifest_probe .probe_results .append (True )
389418
390419 allowed = DockerDeploymentConfig (image = "aaaaaa/bbb/swe-bench:astropy__astropy-12907" )
391420 await sandbox_api ._apply_image_registry_mirror (allowed )
392- assert allowed .image == "rock-a.example.com/rock-public /bbb/swe-bench:astropy__astropy-12907"
421+ assert allowed .image == "rock-a.example.com/aaaaaa /bbb/swe-bench:astropy__astropy-12907"
393422
423+ # "swe-bench:..." has no namespace -> only namespace-replace candidate
424+ stub_manifest_probe .probe_results .append (True )
394425 bare_prefix = DockerDeploymentConfig (image = "swe-bench:python__python-1" )
395426 await sandbox_api ._apply_image_registry_mirror (bare_prefix )
396427 assert bare_prefix .image == "rock-a.example.com/rock-public/swe-bench:python__python-1"
0 commit comments