-
-
Notifications
You must be signed in to change notification settings - Fork 83
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
avoid --abort-on-container-exit to allow containers to react to SIGTERM
- Loading branch information
1 parent
766d196
commit 74c8493
Showing
4 changed files
with
174 additions
and
104 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import io | ||
import logging | ||
import shutil | ||
import subprocess | ||
import threading | ||
|
||
|
||
class DockerRunner: | ||
_containers = None | ||
_cond = None | ||
_timeout = 0 # in seconds | ||
_expired = False | ||
|
||
def __init__(self, timeout: int): | ||
self._containers = [] | ||
self._cond = threading.Condition() | ||
self._timeout = timeout | ||
|
||
def add_container(self, name: str, env: dict): | ||
self._containers.append({"name": name, "env": env}) | ||
|
||
def _run_container(self, cmd: str, env: dict, name: str): | ||
self._execute(cmd, env, name) | ||
with self._cond: | ||
logging.debug("%s container returned.", name) | ||
self._cond.notify() | ||
|
||
def _execute(self, cmd: str, env: dict = {}, name: str = ""): | ||
p = subprocess.Popen( | ||
cmd.split(" "), | ||
bufsize=1, | ||
env=env, | ||
stdout=subprocess.PIPE, | ||
stderr=subprocess.STDOUT, | ||
universal_newlines=True, | ||
) | ||
for line in p.stdout: | ||
ll = "" | ||
if name: | ||
ll = name + ": " | ||
ll = ll + line.rstrip() | ||
logging.debug(ll) | ||
|
||
def _run_timer(self): | ||
logging.debug("Timer expired. Stopping all containers.") | ||
self._expired = True | ||
with self._cond: | ||
self._cond.notify() | ||
|
||
def run(self) -> (str, bool): # returns if the timer expired | ||
# also log to a string, so we can parse the output later | ||
output_string = io.StringIO() | ||
output_stream = logging.StreamHandler(output_string) | ||
output_stream.setLevel(logging.DEBUG) | ||
logging.getLogger().addHandler(output_stream) | ||
|
||
threads = [] | ||
# Start all containers (in separate threads) | ||
docker_compose = shutil.which("docker-compose") | ||
for e in self._containers: | ||
t = threading.Thread( | ||
target=self._run_container, | ||
kwargs={ | ||
"cmd": docker_compose + " up " + e["name"], | ||
"env": e["env"], | ||
"name": e["name"], | ||
}, | ||
) | ||
t.start() | ||
threads.append(t) | ||
# set a timer | ||
timer = threading.Timer(self._timeout, self._run_timer) | ||
timer.start() | ||
|
||
# Wait for the first container to exit. | ||
# Then stop all other docker containers. | ||
with self._cond: | ||
self._cond.wait() | ||
names = [x["name"] for x in self._containers] | ||
self._execute( | ||
shutil.which("docker-compose") + " stop -t 5 " + " ".join(names) | ||
) | ||
# wait for all threads to finish | ||
for t in threads: | ||
t.join() | ||
timer.cancel() | ||
|
||
output = output_string.getvalue() | ||
output_string.close() | ||
logging.getLogger().removeHandler(output_stream) | ||
return output, self._expired |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters