diff --git a/backend/app.py b/backend/app.py index 8394a1fff033ab738fe5bfc01beee90624e1c1c7..242861b2e634df92473ba31e864fe96a503b80b5 100644 --- a/backend/app.py +++ b/backend/app.py @@ -70,7 +70,11 @@ db.init_app(app) # We need this app context in order to talk the database, which is managed by # flask-sqlalchemy, which assumes a flask app context. with app.app_context(): + # Load the list of apps from a configmap and store any missing ones in the + # database. cluster_config.populate_apps() + # Same for the list of oauthclients. + cluster_config.populate_oauthclients() app.register_blueprint(api_v1) app.register_blueprint(web) diff --git a/backend/areas/apps/models.py b/backend/areas/apps/models.py index 0f2b00eca24c11d58a20944bd670003a7d48ca93..069c73751643f42af0619e65c7d6425d4802138d 100644 --- a/backend/areas/apps/models.py +++ b/backend/areas/apps/models.py @@ -309,6 +309,7 @@ class OAuthClientApp(db.Model): # pylint: disable=too-few-public-methods This mapping exists so that * you can have a different name for the OAuth client than for the app, and * you can have multiple OAuth clients that belong to the same app. + Also, some apps might have no OAuth client at all. """ __tablename__ = "oauthclient_app" diff --git a/backend/cluster_config.py b/backend/cluster_config.py index 1ea44e1b4c9daccd7afa76b67f94b230fea07ce3..20ec9e98023dfd01b46a30492f74057aea1a1aed 100644 --- a/backend/cluster_config.py +++ b/backend/cluster_config.py @@ -1,5 +1,5 @@ from database import db -from areas.apps.models import App +from areas.apps.models import App, OAuthClientApp import helpers.kubernetes as k8s import logging @@ -43,3 +43,41 @@ def _populate_apps_from(database_apps, configmap_name): new_app = App(slug=app_slug, name=name, external=external, url=url) db.session.add(new_app) db.session.commit() + +# Read in two configmaps from the cluster, which specify which oauthclients +# should be present in the database. +def populate_oauthclients(): + logging.info("cluster_config: populating oauthclients") + database_oauthclients = {} + for client in OAuthClientApp.query.all(): + id = client.oauthclient_id + database_oauthclients[id] = client + logging.info(f"database oauthclient: {id}") + _populate_oauthclients_from(database_oauthclients, "stackspin-oauthclients") + _populate_oauthclients_from(database_oauthclients, "stackspin-oauthclients-custom") + +# Read a list of oauthclients from a configmap. Check if they are already +# present in the database, and if not, add missing ones there. The value of the +# mapping is taken to be the slug of the app the oauthclient belongs to. +def _populate_oauthclients_from(database_oauthclients, configmap_name): + cm_oauthclients = k8s.get_kubernetes_config_map_data(configmap_name, "flux-system") + if cm_oauthclients is None: + logging.info(f"Could not find configmap '{configmap_name}' in namespace 'flux-system'; ignoring.") + else: + for client_id, client_app in cm_oauthclients.items(): + logging.info(f"configmap oauthclient: {client_id}") + if client_id in database_oauthclients: + logging.info(f" already present in database") + else: + logging.info(f" not present in database, adding!") + # Take the value of the configmap mapping (`client_app`) and + # interpret it as the slug of the app that this oauthclient + # belongs to. + app = App.query.filter_by(slug=client_app).first() + if not app: + logging.error(f" could not find app with slug {client_app}") + continue + new_client = OAuthClientApp(oauthclient_id=client_id, app_id=app.id) + logging.info(f" new oauth client: {new_client}") + db.session.add(new_client) + db.session.commit()