Fix exception handling in the registry health check and make sure the user_loader is registered before the process is forked
This commit is contained in:
parent
e7054a8690
commit
2a89accc49
4 changed files with 58 additions and 43 deletions
26
app.py
26
app.py
|
@ -5,7 +5,7 @@ import yaml
|
||||||
|
|
||||||
from flask import Flask as BaseFlask, Config as BaseConfig, request, Request
|
from flask import Flask as BaseFlask, Config as BaseConfig, request, Request
|
||||||
from flask.ext.principal import Principal
|
from flask.ext.principal import Principal
|
||||||
from flask.ext.login import LoginManager
|
from flask.ext.login import LoginManager, UserMixin
|
||||||
from flask.ext.mail import Mail
|
from flask.ext.mail import Mail
|
||||||
|
|
||||||
import features
|
import features
|
||||||
|
@ -150,5 +150,29 @@ database.configure(app.config)
|
||||||
model.config.app_config = app.config
|
model.config.app_config = app.config
|
||||||
model.config.store = storage
|
model.config.store = storage
|
||||||
|
|
||||||
|
@login_manager.user_loader
|
||||||
|
def load_user(user_uuid):
|
||||||
|
logger.debug('User loader loading deferred user with uuid: %s' % user_uuid)
|
||||||
|
return LoginWrappedDBUser(user_uuid)
|
||||||
|
|
||||||
|
class LoginWrappedDBUser(UserMixin):
|
||||||
|
def __init__(self, user_uuid, db_user=None):
|
||||||
|
self._uuid = user_uuid
|
||||||
|
self._db_user = db_user
|
||||||
|
|
||||||
|
def db_user(self):
|
||||||
|
if not self._db_user:
|
||||||
|
self._db_user = model.get_user_by_uuid(self._uuid)
|
||||||
|
return self._db_user
|
||||||
|
|
||||||
|
def is_authenticated(self):
|
||||||
|
return self.db_user() is not None
|
||||||
|
|
||||||
|
def is_active(self):
|
||||||
|
return self.db_user().verified
|
||||||
|
|
||||||
|
def get_id(self):
|
||||||
|
return unicode(self._uuid)
|
||||||
|
|
||||||
def get_app_url():
|
def get_app_url():
|
||||||
return '%s://%s' % (app.config['PREFERRED_URL_SCHEME'], app.config['SERVER_HOSTNAME'])
|
return '%s://%s' % (app.config['PREFERRED_URL_SCHEME'], app.config['SERVER_HOSTNAME'])
|
||||||
|
|
|
@ -4,14 +4,17 @@ import json
|
||||||
import string
|
import string
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
# Register the various exceptions via decorators.
|
||||||
|
import endpoints.decorated
|
||||||
|
|
||||||
from flask import make_response, render_template, request, abort, session
|
from flask import make_response, render_template, request, abort, session
|
||||||
from flask.ext.login import login_user, UserMixin
|
from flask.ext.login import login_user
|
||||||
from flask.ext.principal import identity_changed
|
from flask.ext.principal import identity_changed
|
||||||
from random import SystemRandom
|
from random import SystemRandom
|
||||||
|
|
||||||
from data import model
|
from data import model
|
||||||
from data.database import db
|
from data.database import db
|
||||||
from app import app, login_manager, oauth_apps, dockerfile_build_queue
|
from app import app, oauth_apps, dockerfile_build_queue, LoginWrappedDBUser
|
||||||
|
|
||||||
from auth.permissions import QuayDeferredPermissionUser
|
from auth.permissions import QuayDeferredPermissionUser
|
||||||
from auth import scopes
|
from auth import scopes
|
||||||
|
@ -21,7 +24,6 @@ from functools import wraps
|
||||||
from config import getFrontendVisibleConfig
|
from config import getFrontendVisibleConfig
|
||||||
from external_libraries import get_external_javascript, get_external_css
|
from external_libraries import get_external_javascript, get_external_css
|
||||||
from endpoints.notificationhelper import spawn_notification
|
from endpoints.notificationhelper import spawn_notification
|
||||||
from util.useremails import CannotSendEmailException
|
|
||||||
|
|
||||||
import features
|
import features
|
||||||
|
|
||||||
|
@ -84,34 +86,8 @@ def param_required(param_name):
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
@login_manager.user_loader
|
|
||||||
def load_user(user_uuid):
|
|
||||||
logger.debug('User loader loading deferred user with uuid: %s' % user_uuid)
|
|
||||||
return _LoginWrappedDBUser(user_uuid)
|
|
||||||
|
|
||||||
|
|
||||||
class _LoginWrappedDBUser(UserMixin):
|
|
||||||
def __init__(self, user_uuid, db_user=None):
|
|
||||||
self._uuid = user_uuid
|
|
||||||
self._db_user = db_user
|
|
||||||
|
|
||||||
def db_user(self):
|
|
||||||
if not self._db_user:
|
|
||||||
self._db_user = model.get_user_by_uuid(self._uuid)
|
|
||||||
return self._db_user
|
|
||||||
|
|
||||||
def is_authenticated(self):
|
|
||||||
return self.db_user() is not None
|
|
||||||
|
|
||||||
def is_active(self):
|
|
||||||
return self.db_user().verified
|
|
||||||
|
|
||||||
def get_id(self):
|
|
||||||
return unicode(self._uuid)
|
|
||||||
|
|
||||||
|
|
||||||
def common_login(db_user):
|
def common_login(db_user):
|
||||||
if login_user(_LoginWrappedDBUser(db_user.uuid, db_user)):
|
if login_user(LoginWrappedDBUser(db_user.uuid, db_user)):
|
||||||
logger.debug('Successfully signed in as: %s (%s)' % (db_user.username, db_user.uuid))
|
logger.debug('Successfully signed in as: %s (%s)' % (db_user.username, db_user.uuid))
|
||||||
new_identity = QuayDeferredPermissionUser(db_user.uuid, 'user_uuid', {scopes.DIRECT_LOGIN})
|
new_identity = QuayDeferredPermissionUser(db_user.uuid, 'user_uuid', {scopes.DIRECT_LOGIN})
|
||||||
identity_changed.send(app, identity=new_identity)
|
identity_changed.send(app, identity=new_identity)
|
||||||
|
@ -121,17 +97,6 @@ def common_login(db_user):
|
||||||
logger.debug('User could not be logged in, inactive?.')
|
logger.debug('User could not be logged in, inactive?.')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@app.errorhandler(model.DataModelException)
|
|
||||||
def handle_dme(ex):
|
|
||||||
logger.exception(ex)
|
|
||||||
return make_response(json.dumps({'message': ex.message}), 400)
|
|
||||||
|
|
||||||
@app.errorhandler(CannotSendEmailException)
|
|
||||||
def handle_emailexception(ex):
|
|
||||||
message = 'Could not send email. Please contact an administrator and report this problem.'
|
|
||||||
return make_response(json.dumps({'message': message}), 400)
|
|
||||||
|
|
||||||
def random_string():
|
def random_string():
|
||||||
random = SystemRandom()
|
random = SystemRandom()
|
||||||
return ''.join([random.choice(string.ascii_uppercase + string.digits) for _ in range(8)])
|
return ''.join([random.choice(string.ascii_uppercase + string.digits) for _ in range(8)])
|
||||||
|
|
19
endpoints/decorated.py
Normal file
19
endpoints/decorated.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import logging
|
||||||
|
import json
|
||||||
|
|
||||||
|
from flask import make_response
|
||||||
|
from app import app
|
||||||
|
from util.useremails import CannotSendEmailException
|
||||||
|
from data import model
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@app.errorhandler(model.DataModelException)
|
||||||
|
def handle_dme(ex):
|
||||||
|
logger.exception(ex)
|
||||||
|
return make_response(json.dumps({'message': ex.message}), 400)
|
||||||
|
|
||||||
|
@app.errorhandler(CannotSendEmailException)
|
||||||
|
def handle_emailexception(ex):
|
||||||
|
message = 'Could not send email. Please contact an administrator and report this problem.'
|
||||||
|
return make_response(json.dumps({'message': message}), 400)
|
|
@ -27,6 +27,9 @@ import features
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# Capture the unverified SSL errors.
|
||||||
|
logging.captureWarnings(True)
|
||||||
|
|
||||||
web = Blueprint('web', __name__)
|
web = Blueprint('web', __name__)
|
||||||
|
|
||||||
STATUS_TAGS = app.config['STATUS_TAGS']
|
STATUS_TAGS = app.config['STATUS_TAGS']
|
||||||
|
@ -167,7 +170,11 @@ def health():
|
||||||
port = ':' + hostname_parts[1]
|
port = ':' + hostname_parts[1]
|
||||||
|
|
||||||
registry_url = '%s://localhost%s/v1/_internal_ping' % (app.config['PREFERRED_URL_SCHEME'], port)
|
registry_url = '%s://localhost%s/v1/_internal_ping' % (app.config['PREFERRED_URL_SCHEME'], port)
|
||||||
registry_healthy = client.get(registry_url, verify=False, timeout=2).status_code == 200
|
registry_healthy = False
|
||||||
|
try:
|
||||||
|
registry_healthy = client.get(registry_url, verify=False, timeout=2).status_code == 200
|
||||||
|
except Exception:
|
||||||
|
logger.exception('Exception when checking registry health: %s', registry_url)
|
||||||
|
|
||||||
check = HealthCheck.get_check(app.config['HEALTH_CHECKER'][0], app.config['HEALTH_CHECKER'][1])
|
check = HealthCheck.get_check(app.config['HEALTH_CHECKER'][0], app.config['HEALTH_CHECKER'][1])
|
||||||
(data, is_healthy) = check.conduct_healthcheck(db_healthy, buildlogs_healthy, registry_healthy)
|
(data, is_healthy) = check.conduct_healthcheck(db_healthy, buildlogs_healthy, registry_healthy)
|
||||||
|
|
Reference in a new issue