From 652ac695b76b4881b5119f5eb15947774998a43b Mon Sep 17 00:00:00 2001 From: Mathieu Leplatre Date: Fri, 25 Nov 2022 16:10:01 +0100 Subject: [PATCH] Fix #461: Add endpoint to expose Acoustic /configuration --- ctms/app.py | 27 +++++++++++++++++++++++++++ ctms/crud.py | 4 +++- tests/unit/test_app.py | 8 ++++++++ tests/unit/test_metrics.py | 4 ++-- 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/ctms/app.py b/ctms/app.py index 908365d7..a614937d 100644 --- a/ctms/app.py +++ b/ctms/app.py @@ -5,6 +5,7 @@ import sys import time from base64 import b64decode +from collections import defaultdict from datetime import datetime, timedelta from functools import lru_cache from typing import Dict, List, Literal, Optional, Tuple, Union @@ -39,6 +40,8 @@ create_contact, create_or_update_contact, get_api_client_by_id, + get_all_acoustic_fields, + get_all_acoustic_newsletters_mapping, get_bulk_contacts, get_contact_by_email_id, get_email, @@ -916,6 +919,30 @@ def metrics(request: Request): return Response(generate_latest(registry), status_code=200, headers=headers) +@app.get("/configuration", tags=["Platform"]) +def configuration( + request: Request, + db_session: Session = Depends(get_db), +): + """Return configuration information, publicly readable""" + all_fields = get_all_acoustic_fields(db_session) + fields_grouped_by_tablename = defaultdict(list) + for entry in all_fields: + fields_grouped_by_tablename[entry.tablename].append(entry.field) + + newsletter_mappings = { + entry.source: entry.destination + for entry in get_all_acoustic_newsletters_mapping(db_session) + } + + return { + "acoustic": { + "sync_fields": fields_grouped_by_tablename, + "newsletter_mappings": newsletter_mappings, + } + } + + def _process_stripe_object( db_session: Session, data: Dict ) -> Tuple[Optional[UUID], Optional[str], Optional[str], StripeIngestActions]: diff --git a/ctms/crud.py b/ctms/crud.py index 7bdcc5ab..8402629d 100644 --- a/ctms/crud.py +++ b/ctms/crud.py @@ -848,7 +848,9 @@ def get_product_id(prod: ProductBaseSchema) -> str: def get_all_acoustic_fields(dbsession, tablename=None): - query = dbsession.query(AcousticField) + query = dbsession.query(AcousticField).order_by( + asc(AcousticField.tablename), asc(AcousticField.field) + ) if tablename: query = query.filter(AcousticField.tablename == tablename) return query.all() diff --git a/tests/unit/test_app.py b/tests/unit/test_app.py index a0958ff5..1d00775c 100644 --- a/tests/unit/test_app.py +++ b/tests/unit/test_app.py @@ -45,3 +45,11 @@ def test_crash_unauthorized(anon_client): resp = anon_client.get("/__crash__") assert resp.status_code == 401 assert resp.json() == {"detail": "Not authenticated"} + + +def test_exposed_configuration(anon_client, dbsession): + resp = anon_client.get("/configuration") + exposed = resp.json() + + assert "fxa_lang" in exposed["acoustic"]["sync_fields"]["main"] + assert exposed["acoustic"]["newsletter_mappings"]["mozilla-rally"] == "sub_rally" diff --git a/tests/unit/test_metrics.py b/tests/unit/test_metrics.py index 36be845a..ee2296f5 100644 --- a/tests/unit/test_metrics.py +++ b/tests/unit/test_metrics.py @@ -20,10 +20,10 @@ # Higher numbers = more ways to slice data, more storage, more processing time for summaries # Cardinality of ctms_requests_total counter -METHOD_PATH_CODE_COMBINATIONS = 50 +METHOD_PATH_CODE_COMBINATIONS = 51 # Cardinality of ctms_requests_duration_seconds histogram -METHOD_PATH_CODEFAM_COMBOS = 36 +METHOD_PATH_CODEFAM_COMBOS = 37 DURATION_BUCKETS = 8 DURATION_COMBINATIONS = METHOD_PATH_CODEFAM_COMBOS * (DURATION_BUCKETS + 2)