-
Notifications
You must be signed in to change notification settings - Fork 62
Make running sytest docker work in worker mode #573
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,35 @@ | ||
| FROM matrixdotorg/sytest:latest | ||
|
|
||
| RUN apt-get -qq install -y python python-dev python-virtualenv | ||
| RUN apt-get -qq update | ||
| RUN apt-get -qq install -y python python-dev python-virtualenv dos2unix eatmydata | ||
|
|
||
| ENV PYTHON=python2 | ||
| ENV PGDATA=/var/lib/postgresql/data | ||
|
|
||
| RUN su -c '/usr/lib/postgresql/9.6/bin/initdb -E "UTF-8" --lc-collate="en_US.UTF-8" --lc-ctype="en_US.UTF-8" --username=postgres' postgres | ||
|
|
||
| # Turn off all the fsync stuff for postgres | ||
| RUN mkdir -p /etc/postgresql/9.6/main/conf.d/ | ||
| RUN echo "fync=off" > /etc/postgresql/9.6/main/conf.d/fsync.conf | ||
| RUN echo "full_page_writes=off" >> /etc/postgresql/9.6/main/conf.d/fsync.conf | ||
|
|
||
| # /src is where we expect Synapse to be | ||
| RUN mkdir /src | ||
|
|
||
| # Create the virutal env upfront so we don't need to keep reinstall dependencies | ||
| RUN $PYTHON -m virtualenv -p $PYTHON /venv/ | ||
| RUN /venv/bin/pip install -q --no-cache-dir matrix-synapse[all] | ||
| RUN /venv/bin/pip install -q --no-cache-dir lxml psycopg2 | ||
|
|
||
| # Uninstall matrix-synapse package so it doesn't collide with the version we try | ||
| # and test | ||
| RUN /venv/bin/pip uninstall -q --no-cache-dir -y matrix-synapse | ||
|
|
||
| # The dockerfile context, when ran by the buildscript, will actually be the | ||
| # repo root, not the docker folder | ||
| ADD docker/synapse_sytest.sh /synapse_sytest.sh | ||
| RUN dos2unix /synapse_sytest.sh | ||
|
|
||
| ADD docker/pydron.py /pydron.py | ||
|
|
||
| ENTRYPOINT ["/synapse_sytest.sh"] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,35 @@ | ||
| FROM matrixdotorg/sytest:latest | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it'd be really nice to combine these two into one dockerfile with an ARG in the same way that synapse's dockerfile works.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. given that the lifespan of the py2 version is only a fortnight, not important, I guess. |
||
|
|
||
| RUN apt-get -qq install -y python3 python3-dev python3-virtualenv | ||
| RUN apt-get -qq update | ||
| RUN apt-get -qq install -y python3 python3-dev python3-virtualenv dos2unix eatmydata | ||
|
|
||
| ENV PYTHON=python3 | ||
| ENV PGDATA=/var/lib/postgresql/data | ||
|
|
||
| RUN su -c '/usr/lib/postgresql/9.6/bin/initdb -E "UTF-8" --lc-collate="en_US.UTF-8" --lc-ctype="en_US.UTF-8" --username=postgres' postgres | ||
|
|
||
| # Turn off all the fsync stuff for postgres | ||
| RUN mkdir -p /etc/postgresql/9.6/main/conf.d/ | ||
| RUN echo "fync=off" > /etc/postgresql/9.6/main/conf.d/fsync.conf | ||
| RUN echo "full_page_writes=off" >> /etc/postgresql/9.6/main/conf.d/fsync.conf | ||
|
|
||
| # /src is where we expect Synapse to be | ||
| RUN mkdir /src | ||
|
|
||
| # Create the virutal env upfront so we don't need to keep reinstall dependencies | ||
| RUN $PYTHON -m virtualenv -p $PYTHON /venv/ | ||
| RUN /venv/bin/pip install -q --no-cache-dir matrix-synapse[all] | ||
| RUN /venv/bin/pip install -q --no-cache-dir lxml psycopg2 | ||
|
|
||
| # Uninstall matrix-synapse package so it doesn't collide with the version we try | ||
| # and test | ||
| RUN /venv/bin/pip uninstall -q --no-cache-dir -y matrix-synapse | ||
|
|
||
| # The dockerfile context, when ran by the buildscript, will actually be the | ||
| # repo root, not the docker folder | ||
| ADD docker/synapse_sytest.sh /synapse_sytest.sh | ||
| RUN dos2unix /synapse_sytest.sh | ||
| ENTRYPOINT ["/synapse_sytest.sh"] | ||
|
|
||
| ADD docker/pydron.py /pydron.py | ||
|
|
||
| ENTRYPOINT ["/synapse_sytest.sh"] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,28 +17,6 @@ def _print(out): | |
| sys.stderr.flush() | ||
|
|
||
|
|
||
| def wait_for_start(process, url): | ||
| """ | ||
| Wait for the start of Synapse by polling its HTTP endpoint. | ||
| """ | ||
| tries = 100 | ||
| while tries != 0: | ||
| tries -= 1 | ||
|
|
||
| try: | ||
| r = requests.get("http://" + url.replace("http://", ""), timeout=5) | ||
| if r.status_code: | ||
| # We don't care what the status code is, just that it's | ||
| # responding. | ||
| return | ||
| except Exception as e: | ||
| time.sleep(0.5) | ||
| pass | ||
|
|
||
| process.kill() | ||
| raise ValueError("Never started, couldn't get %s!" % (url,)) | ||
|
|
||
|
|
||
| _print("Starting pydron...") | ||
|
|
||
| # Sort the args into key:value pairs in a dict | ||
|
|
@@ -65,72 +43,41 @@ def wait_for_start(process, url): | |
| # create a map for it. | ||
| appname_map = {"user-directory": "user_dir"} | ||
|
|
||
| # running is where we'll keep a map of app name to the Popen object (so we can | ||
| # terminate it later). | ||
| running = {} | ||
|
|
||
| try: | ||
| _print("Starting main process") | ||
|
|
||
| # First, try and start Synapse (which will set up the database). | ||
| synapse = ( | ||
| args["--synapse-python"] | ||
| + " -m synapse.app.homeserver --config-path=" | ||
| + " -m synapse.app.homeserver -D --config-path=" | ||
| + args["--synapse-config"] | ||
| ) | ||
| syn = subprocess.Popen( | ||
| shlex.split(synapse), stdout=subprocess.PIPE, stderr=subprocess.STDOUT | ||
| ) | ||
| running["synapse"] = syn | ||
|
|
||
| # Wait for Synapse to start by polling its webserver until it responds. | ||
| wait_for_start(syn, urls["synapse"]) | ||
| subprocess.run(shlex.split(synapse), check=True) | ||
|
|
||
| # Then, start up all the workers. | ||
| for i in configs.keys(): | ||
|
|
||
| # Get the synapse app name from the map, if needed. Otherwise, just | ||
| # replace any dashes with underscores, so they match the Python module | ||
| # name. | ||
| appname = appname_map.get(i, i.replace("-", "_")) | ||
|
|
||
| _print("Starting %s" % (appname,)) | ||
|
|
||
| base = ( | ||
| args["--synapse-python"] | ||
| + " -m synapse.app." | ||
| + appname | ||
| + " -D --config-path=" | ||
| + args["--synapse-config"] | ||
| + " --config-path=" | ||
| + configs[i] | ||
| + " --config-path=" | ||
| + args["--synapse-config"] | ||
| ) | ||
| exc = subprocess.Popen( | ||
| shlex.split(base), stdout=subprocess.PIPE, stderr=subprocess.STDOUT | ||
| ) | ||
| running[i] = exc | ||
|
|
||
| # If we've been given a url for it, poll it until it's up | ||
| if i in urls: | ||
| wait_for_start(exc, urls[i]) | ||
|
|
||
| # Check if any have outright failed to start up (syntax errors, etc). We do | ||
| # this even if we've waited for them to start, because not all workers have | ||
| # a URL. | ||
| failed_units = [] | ||
|
|
||
| for x in running.keys(): | ||
| if x in urls: | ||
| wait_for_start(running[x], urls[x]) | ||
|
|
||
| code = running[x].poll() | ||
|
|
||
| if code: | ||
| _print("%s exited uncleanly with %s!" % (x, code)) | ||
| failed_units.append(x) | ||
|
|
||
| if failed_units: | ||
| raise ValueError("failed units: %r" % (failed_units,)) | ||
| subprocess.run(shlex.split(base), check=True) | ||
|
|
||
| # Nothing failed, let's say we've started and then signal we're up by | ||
| # serving the webserver. | ||
| print("Synapse started!") | ||
| _print("Synapse started!") | ||
|
|
||
| class WebHandler(BaseHTTPRequestHandler): | ||
| def do_GET(self): | ||
|
|
@@ -143,6 +90,8 @@ def do_GET(self): | |
| server = HTTPServer(('', PORT_NUMBER), WebHandler) | ||
| server.serve_forever() | ||
|
|
||
| except KeyboardInterrupt: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what's this for, ooi?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This (empirically) captures when we ask docker to stop half way through a job. |
||
| pass | ||
| except BaseException as e: | ||
| # Log a traceback for debug | ||
| import traceback | ||
|
|
@@ -151,17 +100,7 @@ def do_GET(self): | |
| # If we get told to shut down, log it | ||
| _print("Told to quit because %s" % (repr(e))) | ||
|
|
||
| # Terminate all the workers as cleanly as possible. | ||
| for x in running.keys(): | ||
| if not running[x].returncode: | ||
| _print("Killing %s" % (x,)) | ||
| running[x].kill() | ||
| else: | ||
| _print("%s was already dead" % (x,)) | ||
|
|
||
| # If it's keyboard interrupt, exit cleanly -- sytest is finished. | ||
| if isinstance(e, KeyboardInterrupt): | ||
| sys.exit(0) | ||
|
|
||
| # Otherwise, something bad has happened. | ||
| sys.exit(1) | ||
| finally: | ||
| subprocess.run(["pkill", "-9", "-f", "synapse.app"]) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it feels weird that we are doing this here rather than in Dockerfile-synapsepy2 or whatever