33import functools
44import json
55import logging
6- import traceback
76from typing import Any , Union
87
98from fastapi import (
1918from fastapi .responses import PlainTextResponse
2019from servicelib .fastapi .requests_decorators import cancellable_request
2120
22- from ..core .dependencies import (
23- get_application ,
24- get_application_health ,
25- get_mounted_volumes ,
26- get_rabbitmq ,
27- get_settings ,
28- get_shared_store ,
29- )
21+ from ..core .docker_compose_utils import docker_compose_down , docker_compose_up
3022from ..core .docker_logs import start_log_fetching , stop_log_fetching
3123from ..core .docker_utils import docker_client
3224from ..core .rabbitmq import RabbitMQ
3325from ..core .settings import DynamicSidecarSettings
34- from ..core .shared_handlers import (
35- cleanup_containers_and_volumes ,
36- remove_the_compose_spec ,
37- write_file_and_run_command ,
38- )
3926from ..core .utils import assemble_container_names
4027from ..core .validation import (
4128 InvalidComposeSpec ,
4229 parse_compose_spec ,
4330 validate_compose_spec ,
4431)
45- from ..models .domains .shared_store import SharedStore
4632from ..models .schemas .application_health import ApplicationHealth
33+ from ..models .shared_store import SharedStore
4734from ..modules .directory_watcher import directory_watcher_disabled
4835from ..modules .mounted_fs import MountedVolumes
36+ from ._dependencies import (
37+ get_application ,
38+ get_application_health ,
39+ get_mounted_volumes ,
40+ get_rabbitmq ,
41+ get_settings ,
42+ get_shared_store ,
43+ )
4944
5045logger = logging .getLogger (__name__ )
5146
@@ -55,34 +50,26 @@ async def send_message(rabbitmq: RabbitMQ, message: str) -> None:
5550 await rabbitmq .post_log_message (f"[sidecar] { message } " )
5651
5752
58- async def _task_docker_compose_up (
53+ async def _task_docker_compose_up_and_send_message (
5954 settings : DynamicSidecarSettings ,
6055 shared_store : SharedStore ,
6156 app : FastAPI ,
6257 application_health : ApplicationHealth ,
6358 rabbitmq : RabbitMQ ,
59+ command_timeout : float ,
6460) -> None :
6561 # building is a security risk hence is disabled via "--no-build" parameter
6662 await send_message (rabbitmq , "starting service containers" )
63+ assert shared_store .compose_spec # nosec
6764
6865 with directory_watcher_disabled (app ):
69- await cleanup_containers_and_volumes (shared_store , settings )
70-
71- assert shared_store .compose_spec is not None # nosec
72-
73- command = (
74- "docker-compose --project-name {project} --file {file_path} "
75- "up --no-build --detach"
76- )
77- finished_without_errors , stdout = await write_file_and_run_command (
78- settings = settings ,
79- file_content = shared_store .compose_spec ,
80- command = command ,
81- command_timeout = None ,
66+ r = await docker_compose_up (
67+ shared_store , settings , command_timeout = command_timeout
8268 )
83- message = f"Finished { command } with output\n { stdout } "
8469
85- if finished_without_errors :
70+ message = f"Finished docker-compose up with output\n { r .decoded_stdout } "
71+
72+ if r .success :
8673 await send_message (rabbitmq , "service containers started" )
8774 logger .info (message )
8875 for container_name in shared_store .container_names :
@@ -130,6 +117,12 @@ async def runs_docker_compose_up(
130117 application_health : ApplicationHealth = Depends (get_application_health ),
131118 rabbitmq : RabbitMQ = Depends (get_rabbitmq ),
132119 mounted_volumes : MountedVolumes = Depends (get_mounted_volumes ),
120+ command_timeout : float = Query (
121+ 3600.0 , description = "docker-compose up command timeout run as a background"
122+ ),
123+ validation_timeout : float = Query (
124+ 60.0 , description = "docker-compose config timeout (EXPERIMENTAL)"
125+ ),
133126) -> Union [list [str ], dict [str , Any ]]:
134127 """Expects the docker-compose spec as raw-body utf-8 encoded text"""
135128
@@ -141,24 +134,28 @@ async def runs_docker_compose_up(
141134 settings = settings ,
142135 compose_file_content = body_as_text ,
143136 mounted_volumes = mounted_volumes ,
137+ docker_compose_config_timeout = validation_timeout ,
144138 )
145139 shared_store .container_names = assemble_container_names (
146140 shared_store .compose_spec
147141 )
142+
143+ logger .debug ("Validated compose-spec:\n %s" , f"{ shared_store .compose_spec } " )
144+
148145 except InvalidComposeSpec as e :
149- logger .warning ("Error detected %s" , traceback .format_exc ())
150146 raise HTTPException (status .HTTP_422_UNPROCESSABLE_ENTITY , detail = f"{ e } " ) from e
151147
152148 # run docker-compose in a background queue and return early
153149 assert shared_store .compose_spec is not None # nosec
154150 background_tasks .add_task (
155151 functools .partial (
156- _task_docker_compose_up ,
152+ _task_docker_compose_up_and_send_message ,
157153 settings = settings ,
158154 shared_store = shared_store ,
159155 app = app ,
160156 application_health = application_health ,
161157 rabbitmq = rabbitmq ,
158+ command_timeout = command_timeout ,
162159 )
163160 )
164161
@@ -177,7 +174,7 @@ async def runs_docker_compose_up(
177174)
178175async def runs_docker_compose_down (
179176 command_timeout : float = Query (
180- 10.0 , description = "docker-compose down command timeout default"
177+ 10.0 , description = "docker-compose down command timeout default (EXPERIMENTAL) "
181178 ),
182179 settings : DynamicSidecarSettings = Depends (get_settings ),
183180 shared_store : SharedStore = Depends (get_shared_store ),
@@ -187,14 +184,13 @@ async def runs_docker_compose_down(
187184 and returns the docker-compose output"""
188185 # TODO: convert into long running operation
189186
190- stored_compose_content = shared_store .compose_spec
191- if stored_compose_content is None :
187+ if shared_store .compose_spec is None :
192188 raise HTTPException (
193189 status .HTTP_404_NOT_FOUND ,
194- detail = "No spec for docker- compose down was found" ,
190+ detail = "No compose-specs were found" ,
195191 )
196192
197- finished_without_errors , stdout = await remove_the_compose_spec (
193+ result = await docker_compose_down (
198194 shared_store = shared_store ,
199195 settings = settings ,
200196 command_timeout = command_timeout ,
@@ -203,11 +199,16 @@ async def runs_docker_compose_down(
203199 for container_name in shared_store .container_names :
204200 await stop_log_fetching (app , container_name )
205201
206- if not finished_without_errors :
207- logger .warning ("docker-compose down command finished with errors\n %s" , stdout )
208- raise HTTPException (status .HTTP_422_UNPROCESSABLE_ENTITY , detail = stdout )
202+ if not result .success :
203+ logger .warning (
204+ "docker-compose down command finished with errors\n %s" ,
205+ result .decoded_stdout ,
206+ )
207+ raise HTTPException (
208+ status .HTTP_422_UNPROCESSABLE_ENTITY , detail = result .decoded_stdout
209+ )
209210
210- return stdout
211+ return result . decoded_stdout
211212
212213
213214@containers_router .get (
0 commit comments