Skip to content

Commit

Permalink
Load gunicorn defaults before overriding with app settings
Browse files Browse the repository at this point in the history
fixes: #4917
  • Loading branch information
sdherr authored and mdellweg committed Jan 16, 2024
1 parent efb17a7 commit 55043f3
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 28 deletions.
1 change: 1 addition & 0 deletions CHANGES/4917.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Enabled the gunicorn applications for ``pulpcore-api`` and ``pulpcore-content`` to load configurations from the "gunicorn.conf.py" file.
23 changes: 9 additions & 14 deletions pulpcore/app/entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
from django.db import connection
from django.db.utils import InterfaceError, OperationalError
from gunicorn.workers.sync import SyncWorker
from gunicorn.app.base import BaseApplication

from pulpcore.app.apps import pulp_plugin_configs
from pulpcore.app.pulpcore_gunicorn_application import PulpcoreGunicornApplication

logger = getLogger(__name__)

Expand Down Expand Up @@ -80,19 +80,14 @@ def run(self):
self.api_app_status.delete()


class PulpcoreApiApplication(BaseApplication):
def __init__(self, options):
self.options = options or {}
super().__init__()

def load_config(self):
[
self.cfg.set(key.lower(), value)
for key, value in self.options.items()
if value is not None
]
self.cfg.set("default_proc_name", "pulpcore-api")
self.cfg.set("worker_class", PulpApiWorker.__module__ + "." + PulpApiWorker.__qualname__)
class PulpcoreApiApplication(PulpcoreGunicornApplication):
def load_app_specific_config(self):
self.set_option("default_proc_name", "pulpcore-api", enforced=True)
self.set_option(
"worker_class",
PulpApiWorker.__module__ + "." + PulpApiWorker.__qualname__,
enforced=True,
)

def load(self):
using_pulp_api_worker.set(True)
Expand Down
71 changes: 71 additions & 0 deletions pulpcore/app/pulpcore_gunicorn_application.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import sys

from gunicorn.app.base import Application


class PulpcoreGunicornApplication(Application):
"""
A common class for the api and content applications to inherit from that loads the default
gunicorn configs (including from a config file if one exists) and then overrides with the values
specified in the init scripts. With warnings / errors if the user overrides something that won't
take effect or cannot be changed.
"""

def __init__(self, options):
self.options = options or {}
super().__init__()

def init(self, *args, **kwargs):
"""
A hook for setting application-specific configs, which we instead do below in load_config
where it's non-overridable.
"""
pass

def set_option(self, key, value, enforced=False):
if value is None: # not specified by init script
return

def _is_default(key, value):
if value is None:
return True
defaults = {
"default_proc_name": "gunicorn",
"reload_extra_files": [],
"access_log_format": '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"',
"bind": ["127.0.0.1:8000"],
"threads": 1,
"worker_class": "<class 'gunicorn.workers.sync.SyncWorker'>",
}
return key in defaults and str(defaults[key]) == str(value)

current_value = getattr(self.cfg, key, None)
if not _is_default(key, current_value) and str(current_value) != str(value):
if enforced:
sys.stderr.write(
f"Error: {key} is set to {current_value} in gunicorn.conf.py but must not be "
"changed!\n"
)
exit(1)
else:
sys.stderr.write(
f"Warning: {key} is set to {current_value} in gunicorn.conf.py but is "
f"overridden to {value} by init script!\n"
)

self.cfg.set(key, value)

def load_config(self):
# Load default gunicorn configs, including reading from the default config file.
super().load_config()
# Override with settings that we've specified in the startup script.
for key, value in self.options.items():
self.set_option(key, value)
self.set_option("threads", "1", enforced=True)
self.load_app_specific_config()

def load_app_specific_config(self):
raise NotImplementedError

def load(self):
raise NotImplementedError
19 changes: 5 additions & 14 deletions pulpcore/content/entrypoint.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
import click
from gunicorn.app.base import BaseApplication
from pulpcore.app.pulpcore_gunicorn_application import PulpcoreGunicornApplication


class PulpcoreContentApplication(BaseApplication):
def __init__(self, options):
self.options = options or {}
super().__init__()

def load_config(self):
[
self.cfg.set(key.lower(), value)
for key, value in self.options.items()
if value is not None
]
self.cfg.set("default_proc_name", "pulpcore-content")
self.cfg.set("worker_class", "aiohttp.GunicornWebWorker")
class PulpcoreContentApplication(PulpcoreGunicornApplication):
def load_app_specific_config(self):
self.set_option("default_proc_name", "pulpcore-content", enforced=True)
self.set_option("worker_class", "aiohttp.GunicornWebWorker", enforced=True)

def load(self):
import pulpcore.content
Expand Down

0 comments on commit 55043f3

Please sign in to comment.