22
33from __future__ import annotations
44
5+ import subprocess
56from contextlib import nullcontext
67from pathlib import Path
78
89import pytest
910
1011import app .startup .runtime_admin as init_module
12+ from app .core .entities .admin_errors import InitConflictError , InitDependencyError
1113from app .core .entities .machine_config import (
1214 BackupState ,
1315 DatabaseState ,
1618 ManagedInstanceState ,
1719)
1820from app .infrastructure .db .admin .provisioning import managed_local as managed_runtime
21+ from app .infrastructure .db .admin .provisioning import docker_prerequisites
1922from app .infrastructure .local_state .repo_registration_store import RepoRegistration
2023from app .entrypoints .cli .presenters .init import render_success_lines as render_init_lines
2124
@@ -691,7 +694,32 @@ def test_external_init_should_skip_managed_container_setup(
691694 assert saved [0 ].runtime_mode == "external_postgres"
692695
693696
694- def test_ensure_managed_runtime_ready_should_start_managed_container_and_wait (
697+ def test_ensure_managed_runtime_ready_should_skip_docker_when_postgres_is_ready (
698+ monkeypatch ,
699+ ) -> None :
700+ """operation readiness should use an available configured database directly."""
701+
702+ config = _machine_config (bootstrap_state = "ready" )
703+ calls : list [object ] = []
704+
705+ monkeypatch .setattr (init_module , "try_load_machine_config" , lambda : (config , None ))
706+ monkeypatch .setattr (
707+ init_module ,
708+ "ensure_managed_runtime_available" ,
709+ lambda : (_ for _ in ()).throw (AssertionError ("unexpected docker check" )),
710+ )
711+ monkeypatch .setattr (
712+ init_module ,
713+ "wait_for_postgres" ,
714+ lambda dsn , timeout_seconds : calls .append ((dsn , timeout_seconds )),
715+ )
716+
717+ init_module .ensure_managed_runtime_ready ()
718+
719+ assert calls == [(config .database .admin_dsn , 0 )]
720+
721+
722+ def test_ensure_managed_runtime_ready_should_start_unavailable_managed_container (
695723 monkeypatch ,
696724) -> None :
697725 """operation readiness should start the configured managed runtime once."""
@@ -708,21 +736,45 @@ def test_ensure_managed_runtime_ready_should_start_managed_container_and_wait(
708736 "ensure_existing_managed_container_running" ,
709737 lambda received : calls .append (("container" , received )) or True ,
710738 )
711- monkeypatch .setattr (
712- init_module ,
713- "wait_for_postgres" ,
714- lambda dsn , timeout_seconds : calls .append (("wait" , dsn , timeout_seconds )),
715- )
739+
740+ def wait (dsn : str , timeout_seconds : int ) -> None :
741+ calls .append (("wait" , dsn , timeout_seconds ))
742+ if timeout_seconds == 0 :
743+ raise InitConflictError ("not ready" )
744+
745+ monkeypatch .setattr (init_module , "wait_for_postgres" , wait )
716746
717747 init_module .ensure_managed_runtime_ready ()
718748
719749 assert calls == [
750+ ("wait" , config .database .admin_dsn , 0 ),
720751 "deps" ,
721752 ("container" , config ),
722753 ("wait" , config .database .admin_dsn , 15 ),
723754 ]
724755
725756
757+ def test_docker_readiness_error_should_include_docker_detail (monkeypatch ) -> None :
758+ """docker readiness should preserve the failure reported by Docker."""
759+
760+ monkeypatch .setattr (
761+ docker_prerequisites .shutil , "which" , lambda name : "/usr/bin/docker"
762+ )
763+ monkeypatch .setattr (
764+ docker_prerequisites .subprocess ,
765+ "run" ,
766+ lambda * args , ** kwargs : subprocess .CompletedProcess (
767+ args = ["docker" , "info" ],
768+ returncode = 1 ,
769+ stdout = "" ,
770+ stderr = "permission denied while connecting to the Docker socket" ,
771+ ),
772+ )
773+
774+ with pytest .raises (InitDependencyError , match = "permission denied" ):
775+ docker_prerequisites .ensure_docker_runtime_available ()
776+
777+
726778@pytest .mark .parametrize (
727779 "loaded_factory" ,
728780 [
0 commit comments